blob: 12bca02c3a0bfd19290d182856523f6f0afa1d48 [file] [log] [blame]
Thierry Fourniere726b142016-02-11 17:57:57 +01001/*
2 * Lua safe functions
3 *
4 * Copyright 2015-2016 Thierry Fournier <tfournier@arpalert.org>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 *
12 * All the functions in this file runs with a Lua stack, and can
Thierry Fournierfb0b5462016-01-21 09:28:58 +010013 * return with a longjmp. All of these function must be launched
14 * in an environment able to catch a longjmp, otherwise a
15 * critical error can be raised.
16 */
17#include <lauxlib.h>
18#include <lua.h>
19#include <lualib.h>
20
Willy Tarreau83487a82020-06-04 20:19:54 +020021#include <haproxy/cli-t.h>
Willy Tarreau86416052020-06-04 09:20:54 +020022#include <haproxy/hlua-t.h>
Willy Tarreaucd72d8c2020-06-02 19:11:26 +020023#include <haproxy/http.h>
Willy Tarreauaeed4a82020-06-04 22:01:04 +020024#include <haproxy/log.h>
Willy Tarreau6131d6a2020-06-02 16:48:09 +020025#include <haproxy/net_helper.h>
Willy Tarreau7cd8b6e2020-06-02 17:32:26 +020026#include <haproxy/regex.h>
Willy Tarreau2eec9b52020-06-04 19:58:55 +020027#include <haproxy/stats.h>
Willy Tarreau92b4f132020-06-01 11:05:15 +020028#include <haproxy/time.h>
Thierry Fournierb1f46562016-01-21 09:46:15 +010029
Thierry Fournierf61aa632016-02-19 20:56:00 +010030#include <types/proxy.h>
Thierry Fournier49d48422016-02-19 12:09:29 +010031
Thierry Fournierf61aa632016-02-19 20:56:00 +010032#include <proto/proxy.h>
33#include <proto/server.h>
Willy Tarreau872f2ea2020-06-04 18:46:44 +020034#include <haproxy/stick_table.h>
Thierry Fournier94ed1c12016-02-24 08:06:32 +010035
Thierry Fournier1de16592016-01-27 09:49:07 +010036/* Contains the class reference of the concat object. */
37static int class_concat_ref;
Thierry Fournierf61aa632016-02-19 20:56:00 +010038static int class_proxy_ref;
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +010039static int class_server_ref;
Thierry Fournierff480422016-02-25 08:36:46 +010040static int class_listener_ref;
Thierry FOURNIER31904272017-10-25 12:59:51 +020041static int class_regex_ref;
Adis Nezirovic8878f8e2018-07-13 12:18:33 +020042static int class_stktable_ref;
Thierry Fournier1de16592016-01-27 09:49:07 +010043
Thierry Fournierf61aa632016-02-19 20:56:00 +010044#define STATS_LEN (MAX((int)ST_F_TOTAL_FIELDS, (int)INF_TOTAL_FIELDS))
Thierry Fourniereea77c02016-03-18 08:47:13 +010045
Thierry FOURNIERffbad792017-07-12 11:39:04 +020046static THREAD_LOCAL struct field stats[STATS_LEN];
Thierry Fourniereea77c02016-03-18 08:47:13 +010047
Thierry FOURNIER / OZON.IO7f3aa8b2016-11-24 20:37:38 +010048int hlua_checkboolean(lua_State *L, int index)
49{
50 if (!lua_isboolean(L, index))
51 luaL_argerror(L, index, "boolean expected");
52 return lua_toboolean(L, index);
53}
54
Adis Nezirovic8878f8e2018-07-13 12:18:33 +020055/* Helper to push unsigned integers to Lua stack, respecting Lua limitations */
56static int hlua_fcn_pushunsigned(lua_State *L, unsigned int val)
57{
58#if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
59 lua_pushinteger(L, val);
60#else
61 if (val > INT_MAX)
62 lua_pushnumber(L, (lua_Number)val);
63 else
64 lua_pushinteger(L, (int)val);
65#endif
66 return 1;
67}
68
69/* Helper to push unsigned long long to Lua stack, respecting Lua limitations */
70static int hlua_fcn_pushunsigned_ll(lua_State *L, unsigned long long val) {
71#if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
72 /* 64 bits case, U64 is supported until LLONG_MAX */
73 if (val > LLONG_MAX)
74 lua_pushnumber(L, (lua_Number)val);
75 else
76 lua_pushinteger(L, val);
77#else
78 /* 32 bits case, U64 is supported until INT_MAX */
79 if (val > INT_MAX)
80 lua_pushnumber(L, (lua_Number)val);
81 else
82 lua_pushinteger(L, (int)val);
83#endif
84 return 1;
85}
86
Joseph Herlantb3d92e32018-11-15 09:35:04 -080087/* This function gets a struct field and converts it in Lua
88 * variable. The variable is pushed at the top of the stack.
Thierry Fournier8b0d6e12016-03-16 18:29:13 +010089 */
90int hlua_fcn_pushfield(lua_State *L, struct field *field)
91{
92 /* The lua_Integer is always signed. Its length depends on
Joseph Herlantb3d92e32018-11-15 09:35:04 -080093 * compilation options, so the following code is conditioned
Thierry Fournier8b0d6e12016-03-16 18:29:13 +010094 * by some macros. Windows maros are not supported.
95 * If the number cannot be represented as integer, we try to
96 * convert to float.
97 */
98 switch (field_format(field, 0)) {
99
100 case FF_EMPTY:
101 lua_pushnil(L);
102 return 1;
103
104 case FF_S32:
105 /* S32 is always supported. */
106 lua_pushinteger(L, field->u.s32);
107 return 1;
108
109 case FF_U32:
110#if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
111 /* 64 bits case, U32 is always supported */
112 lua_pushinteger(L, field->u.u32);
113#else
114 /* 32 bits case, U32 is supported until INT_MAX. */
115 if (field->u.u32 > INT_MAX)
116 lua_pushnumber(L, (lua_Number)field->u.u32);
117 else
118 lua_pushinteger(L, field->u.u32);
119#endif
120 return 1;
121
122 case FF_S64:
123#if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
124 /* 64 bits case, S64 is always supported */
125 lua_pushinteger(L, field->u.s64);
126#else
Ilya Shipitsince7b00f2020-03-23 22:28:40 +0500127 /* 64 bits case, S64 is supported between INT_MIN and INT_MAX */
Thierry Fournier8b0d6e12016-03-16 18:29:13 +0100128 if (field->u.s64 < INT_MIN || field->u.s64 > INT_MAX)
129 lua_pushnumber(L, (lua_Number)field->u.s64);
130 else
131 lua_pushinteger(L, (int)field->u.s64);
132#endif
133 return 1;
134
135 case FF_U64:
136#if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
137 /* 64 bits case, U64 is supported until LLONG_MAX */
138 if (field->u.u64 > LLONG_MAX)
139 lua_pushnumber(L, (lua_Number)field->u.u64);
140 else
141 lua_pushinteger(L, field->u.u64);
142#else
143 /* 64 bits case, U64 is supported until INT_MAX */
144 if (field->u.u64 > INT_MAX)
145 lua_pushnumber(L, (lua_Number)field->u.u64);
146 else
147 lua_pushinteger(L, (int)field->u.u64);
148#endif
149 return 1;
150
151 case FF_STR:
152 lua_pushstring(L, field->u.str);
153 return 1;
154
155 default:
156 break;
157 }
158
159 /* Default case, never reached. */
160 lua_pushnil(L);
161 return 1;
162}
163
Thierry Fournier94ed1c12016-02-24 08:06:32 +0100164/* Some string are started or terminated by blank chars,
165 * this function removes the spaces, tabs, \r and
166 * \n at the begin and at the end of the string "str", and
167 * push the result in the lua stack.
168 * Returns a pointer to the Lua internal copy of the string.
169 */
170const char *hlua_pushstrippedstring(lua_State *L, const char *str)
171{
172 const char *p;
173 const char *e;
174
175 for (p = str; HTTP_IS_LWS(*p); p++);
176 for (e = p + strlen(p) - 1; e > p && HTTP_IS_LWS(*e); e--);
177
178 return lua_pushlstring(L, p, e - p);
179}
180
Thierry Fournierddd89882016-02-22 19:52:08 +0100181/* The three following functions are useful for adding entries
182 * in a table. These functions takes a string and respectively an
183 * integer, a string or a function and add it to the table in the
184 * top of the stack.
185 *
186 * These functions throws an error if no more stack size is
187 * available.
188 */
189void hlua_class_const_int(lua_State *L, const char *name, int value)
190{
Thierry Fournierddd89882016-02-22 19:52:08 +0100191 lua_pushstring(L, name);
192 lua_pushinteger(L, value);
193 lua_rawset(L, -3);
194}
195void hlua_class_const_str(lua_State *L, const char *name, const char *value)
196{
Thierry Fournierddd89882016-02-22 19:52:08 +0100197 lua_pushstring(L, name);
198 lua_pushstring(L, value);
199 lua_rawset(L, -3);
200}
201void hlua_class_function(lua_State *L, const char *name, int (*function)(lua_State *L))
202{
Thierry Fournierddd89882016-02-22 19:52:08 +0100203 lua_pushstring(L, name);
204 lua_pushcclosure(L, function, 0);
205 lua_rawset(L, -3);
206}
207
Joseph Herlantb3d92e32018-11-15 09:35:04 -0800208/* This function returns a string containing the HAProxy object name. */
Thierry Fournierddd89882016-02-22 19:52:08 +0100209int hlua_dump_object(struct lua_State *L)
210{
211 const char *name = (const char *)lua_tostring(L, lua_upvalueindex(1));
212 lua_pushfstring(L, "HAProxy class %s", name);
213 return 1;
214}
215
Thierry Fournier45e78d72016-02-19 18:34:46 +0100216/* This function register a table as metatable and. It names
217 * the metatable, and returns the associated reference.
Ilya Shipitsince7b00f2020-03-23 22:28:40 +0500218 * The original table is popped from the top of the stack.
Thierry Fournier45e78d72016-02-19 18:34:46 +0100219 * "name" is the referenced class name.
220 */
221int hlua_register_metatable(struct lua_State *L, char *name)
222{
223 /* Check the type of the top element. it must be
224 * a table.
225 */
226 if (lua_type(L, -1) != LUA_TTABLE)
227 luaL_error(L, "hlua_register_metatable() requires a type Table "
228 "in the top of the stack");
229
230 /* Add the __tostring function which identify the
231 * created object.
232 */
233 lua_pushstring(L, "__tostring");
234 lua_pushstring(L, name);
235 lua_pushcclosure(L, hlua_dump_object, 1);
236 lua_rawset(L, -3);
237
238 /* Register a named entry for the table. The table
Ilya Shipitsince7b00f2020-03-23 22:28:40 +0500239 * reference is copied first because the function
Thierry Fournier45e78d72016-02-19 18:34:46 +0100240 * lua_setfield() pop the entry.
241 */
242 lua_pushvalue(L, -1);
243 lua_setfield(L, LUA_REGISTRYINDEX, name);
244
245 /* Creates the reference of the object. The
246 * function luaL_ref pop the top of the stack.
247 */
248 return luaL_ref(L, LUA_REGISTRYINDEX);
249}
250
Thierry Fournier9e7e3ea2016-01-27 09:55:30 +0100251/* Return an object of the expected type, or throws an error. */
252void *hlua_checkudata(lua_State *L, int ud, int class_ref)
253{
254 void *p;
Thierry Fournier53518272016-01-27 10:34:09 +0100255 int ret;
Thierry Fournier9e7e3ea2016-01-27 09:55:30 +0100256
257 /* Check if the stack entry is an array. */
258 if (!lua_istable(L, ud))
Thierry Fournier53518272016-01-27 10:34:09 +0100259 luaL_argerror(L, ud, NULL);
260
261 /* pop the metatable of the referencecd object. */
262 if (!lua_getmetatable(L, ud))
263 luaL_argerror(L, ud, NULL);
264
265 /* pop the expected metatable. */
266 lua_rawgeti(L, LUA_REGISTRYINDEX, class_ref);
267
Thierry Fournier9e7e3ea2016-01-27 09:55:30 +0100268 /* Check if the metadata have the expected type. */
Thierry Fournier53518272016-01-27 10:34:09 +0100269 ret = lua_rawequal(L, -1, -2);
270 lua_pop(L, 2);
271 if (!ret)
272 luaL_argerror(L, ud, NULL);
273
Thierry Fournier9e7e3ea2016-01-27 09:55:30 +0100274 /* Push on the stack at the entry [0] of the table. */
275 lua_rawgeti(L, ud, 0);
Thierry Fournier53518272016-01-27 10:34:09 +0100276
Thierry Fournier9e7e3ea2016-01-27 09:55:30 +0100277 /* Check if this entry is userdata. */
278 p = lua_touserdata(L, -1);
279 if (!p)
Thierry Fournier53518272016-01-27 10:34:09 +0100280 luaL_argerror(L, ud, NULL);
281
Thierry Fournier9e7e3ea2016-01-27 09:55:30 +0100282 /* Remove the entry returned by lua_rawgeti(). */
283 lua_pop(L, 1);
Thierry Fournier53518272016-01-27 10:34:09 +0100284
Thierry Fournier9e7e3ea2016-01-27 09:55:30 +0100285 /* Return the associated struct. */
286 return p;
287}
288
Thierry Fournierb1f46562016-01-21 09:46:15 +0100289/* This function return the current date at epoch format in milliseconds. */
290int hlua_now(lua_State *L)
291{
292 lua_newtable(L);
293 lua_pushstring(L, "sec");
294 lua_pushinteger(L, now.tv_sec);
295 lua_rawset(L, -3);
296 lua_pushstring(L, "usec");
297 lua_pushinteger(L, now.tv_usec);
298 lua_rawset(L, -3);
299 return 1;
300}
301
Thierry Fournier1550d5d2016-01-21 09:35:41 +0100302/* This functions expects a Lua string as HTTP date, parse it and
303 * returns an integer containing the epoch format of the date, or
304 * nil if the parsing fails.
305 */
306static int hlua_parse_date(lua_State *L, int (*fcn)(const char *, int, struct tm*))
307{
308 const char *str;
309 size_t len;
310 struct tm tm;
311 time_t time;
312
313 str = luaL_checklstring(L, 1, &len);
314
315 if (!fcn(str, len, &tm)) {
316 lua_pushnil(L);
317 return 1;
318 }
319
320 /* This function considers the content of the broken-down time
321 * is exprimed in the UTC timezone. timegm don't care about
322 * the gnu variable tm_gmtoff. If gmtoff is set, or if you know
323 * the timezone from the broken-down time, it must be fixed
324 * after the conversion.
325 */
Willy Tarreauabd9bb22017-07-19 19:08:48 +0200326 time = my_timegm(&tm);
Thierry Fournier1550d5d2016-01-21 09:35:41 +0100327 if (time == -1) {
328 lua_pushnil(L);
329 return 1;
330 }
331
332 lua_pushinteger(L, (int)time);
333 return 1;
334}
335static int hlua_http_date(lua_State *L)
336{
337 return hlua_parse_date(L, parse_http_date);
338}
339static int hlua_imf_date(lua_State *L)
340{
341 return hlua_parse_date(L, parse_imf_date);
342}
343static int hlua_rfc850_date(lua_State *L)
344{
345 return hlua_parse_date(L, parse_rfc850_date);
346}
347static int hlua_asctime_date(lua_State *L)
348{
349 return hlua_parse_date(L, parse_asctime_date);
350}
351
Thierry Fourniereea77c02016-03-18 08:47:13 +0100352static int hlua_get_info(lua_State *L)
353{
354 int i;
355
356 stats_fill_info(stats, STATS_LEN);
357
358 lua_newtable(L);
359 for (i=0; i<INF_TOTAL_FIELDS; i++) {
Willy Tarreaueaa55372019-10-09 07:39:11 +0200360 lua_pushstring(L, info_fields[i].name);
Thierry Fourniereea77c02016-03-18 08:47:13 +0100361 hlua_fcn_pushfield(L, &stats[i]);
362 lua_settable(L, -3);
363 }
364 return 1;
365}
366
Thierry Fournier49d48422016-02-19 12:09:29 +0100367static struct hlua_concat *hlua_check_concat(lua_State *L, int ud)
Thierry Fournier1de16592016-01-27 09:49:07 +0100368{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200369 return (hlua_checkudata(L, ud, class_concat_ref));
Thierry Fournier1de16592016-01-27 09:49:07 +0100370}
371
372static int hlua_concat_add(lua_State *L)
373{
Thierry Fournier49d48422016-02-19 12:09:29 +0100374 struct hlua_concat *b;
375 char *buffer;
376 char *new;
Thierry Fournier1de16592016-01-27 09:49:07 +0100377 const char *str;
378 size_t l;
379
380 /* First arg must be a concat object. */
381 b = hlua_check_concat(L, 1);
382
383 /* Second arg must be a string. */
384 str = luaL_checklstring(L, 2, &l);
385
Thierry Fournier49d48422016-02-19 12:09:29 +0100386 /* Get the buffer. */
387 lua_rawgeti(L, 1, 1);
388 buffer = lua_touserdata(L, -1);
389 lua_pop(L, 1);
390
391 /* Update the buffer size if it s required. The old buffer
392 * is crushed by the new in the object array, so it will
393 * be deleted by the GC.
394 * Note that in the first loop, the "new" variable is only
395 * used as a flag.
396 */
397 new = NULL;
398 while (b->size - b->len < l) {
399 b->size += HLUA_CONCAT_BLOCSZ;
400 new = buffer;
401 }
402 if (new) {
403 new = lua_newuserdata(L, b->size);
404 memcpy(new, buffer, b->len);
405 lua_rawseti(L, 1, 1);
406 buffer = new;
407 }
408
409 /* Copy string, and update metadata. */
410 memcpy(buffer + b->len, str, l);
411 b->len += l;
Thierry Fournier1de16592016-01-27 09:49:07 +0100412 return 0;
413}
414
415static int hlua_concat_dump(lua_State *L)
416{
Thierry Fournier49d48422016-02-19 12:09:29 +0100417 struct hlua_concat *b;
418 char *buffer;
Thierry Fournier1de16592016-01-27 09:49:07 +0100419
420 /* First arg must be a concat object. */
421 b = hlua_check_concat(L, 1);
422
Thierry Fournier49d48422016-02-19 12:09:29 +0100423 /* Get the buffer. */
424 lua_rawgeti(L, 1, 1);
425 buffer = lua_touserdata(L, -1);
426 lua_pop(L, 1);
427
Ilya Shipitsince7b00f2020-03-23 22:28:40 +0500428 /* Push the soncatenated string in the stack. */
Thierry Fournier49d48422016-02-19 12:09:29 +0100429 lua_pushlstring(L, buffer, b->len);
Thierry Fournier1de16592016-01-27 09:49:07 +0100430 return 1;
431}
432
433int hlua_concat_new(lua_State *L)
434{
Thierry Fournier49d48422016-02-19 12:09:29 +0100435 struct hlua_concat *b;
Thierry Fournier1de16592016-01-27 09:49:07 +0100436
437 lua_newtable(L);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200438 b = lua_newuserdata(L, sizeof(*b));
Thierry Fournier49d48422016-02-19 12:09:29 +0100439 b->size = HLUA_CONCAT_BLOCSZ;
440 b->len = 0;
Thierry Fournier1de16592016-01-27 09:49:07 +0100441 lua_rawseti(L, -2, 0);
Thierry Fournier49d48422016-02-19 12:09:29 +0100442 lua_newuserdata(L, HLUA_CONCAT_BLOCSZ);
443 lua_rawseti(L, -2, 1);
Thierry Fournier1de16592016-01-27 09:49:07 +0100444
445 lua_rawgeti(L, LUA_REGISTRYINDEX, class_concat_ref);
446 lua_setmetatable(L, -2);
447
Thierry Fournier1de16592016-01-27 09:49:07 +0100448 return 1;
449}
450
451static int concat_tostring(lua_State *L)
452{
453 const void *ptr = lua_topointer(L, 1);
454 lua_pushfstring(L, "Concat object: %p", ptr);
455 return 1;
456}
457
458static int hlua_concat_init(lua_State *L)
459{
460 /* Creates the buffered concat object. */
461 lua_newtable(L);
462
463 lua_pushstring(L, "__tostring");
464 lua_pushcclosure(L, concat_tostring, 0);
465 lua_settable(L, -3);
466
467 lua_pushstring(L, "__index"); /* Creates the index entry. */
468 lua_newtable(L); /* The "__index" content. */
469
470 lua_pushstring(L, "add");
471 lua_pushcclosure(L, hlua_concat_add, 0);
472 lua_settable(L, -3);
473
474 lua_pushstring(L, "dump");
475 lua_pushcclosure(L, hlua_concat_dump, 0);
476 lua_settable(L, -3);
477
478 lua_settable(L, -3); /* Sets the __index entry. */
479 class_concat_ref = luaL_ref(L, LUA_REGISTRYINDEX);
480
481 return 1;
482}
483
Adis Nezirovic8878f8e2018-07-13 12:18:33 +0200484int hlua_fcn_new_stktable(lua_State *L, struct stktable *tbl)
485{
486 lua_newtable(L);
487
488 /* Pop a class stktbl metatable and affect it to the userdata. */
489 lua_rawgeti(L, LUA_REGISTRYINDEX, class_stktable_ref);
490 lua_setmetatable(L, -2);
491
492 lua_pushlightuserdata(L, tbl);
493 lua_rawseti(L, -2, 0);
494 return 1;
495}
496
497static struct stktable *hlua_check_stktable(lua_State *L, int ud)
498{
499 return hlua_checkudata(L, ud, class_stktable_ref);
500}
501
502/* Extract stick table attributes into Lua table */
503int hlua_stktable_info(lua_State *L)
504{
505 struct stktable *tbl;
506 int dt;
507
508 tbl = hlua_check_stktable(L, 1);
509
510 if (!tbl->id) {
511 lua_pushnil(L);
512 return 1;
513 }
514
515 lua_newtable(L);
516
517 lua_pushstring(L, "type");
518 lua_pushstring(L, stktable_types[tbl->type].kw);
519 lua_settable(L, -3);
520
521 lua_pushstring(L, "length");
522 lua_pushinteger(L, tbl->key_size);
523 lua_settable(L, -3);
524
525 lua_pushstring(L, "size");
526 hlua_fcn_pushunsigned(L, tbl->size);
527 lua_settable(L, -3);
528
529 lua_pushstring(L, "used");
530 hlua_fcn_pushunsigned(L, tbl->current);
531 lua_settable(L, -3);
532
533 lua_pushstring(L, "nopurge");
534 lua_pushboolean(L, tbl->nopurge > 0);
535 lua_settable(L, -3);
536
537 lua_pushstring(L, "expire");
538 lua_pushinteger(L, tbl->expire);
539 lua_settable(L, -3);
540
541 /* Save data types periods (if applicable) in 'data' table */
542 lua_pushstring(L, "data");
543 lua_newtable(L);
544
545 for (dt = 0; dt < STKTABLE_DATA_TYPES; dt++) {
546 if (tbl->data_ofs[dt] == 0)
547 continue;
548
549 lua_pushstring(L, stktable_data_types[dt].name);
550
551 if (stktable_data_types[dt].arg_type == ARG_T_DELAY)
552 lua_pushinteger(L, tbl->data_arg[dt].u);
553 else
554 lua_pushinteger(L, -1);
555
556 lua_settable(L, -3);
557 }
558
559 lua_settable(L, -3);
560
561 return 1;
562}
563
564/* Helper to get extract stick table entry into Lua table */
565static void hlua_stktable_entry(lua_State *L, struct stktable *t, struct stksess *ts)
566{
567 int dt;
568 void *ptr;
569
570 for (dt = 0; dt < STKTABLE_DATA_TYPES; dt++) {
571
572 if (t->data_ofs[dt] == 0)
573 continue;
574
575 lua_pushstring(L, stktable_data_types[dt].name);
576
577 ptr = stktable_data_ptr(t, ts, dt);
578 switch (stktable_data_types[dt].std_type) {
579 case STD_T_SINT:
580 lua_pushinteger(L, stktable_data_cast(ptr, std_t_sint));
581 break;
582 case STD_T_UINT:
583 hlua_fcn_pushunsigned(L, stktable_data_cast(ptr, std_t_uint));
584 break;
585 case STD_T_ULL:
586 hlua_fcn_pushunsigned_ll(L, stktable_data_cast(ptr, std_t_ull));
587 break;
588 case STD_T_FRQP:
589 lua_pushinteger(L, read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
590 t->data_arg[dt].u));
591 break;
Adis Nezirovicad9f9ed2020-05-05 13:57:28 +0200592 case STD_T_DICT: {
593 struct dict_entry *de;
594 de = stktable_data_cast(ptr, std_t_dict);
595 lua_pushstring(L, de ? (char *)de->value.key : "-");
596 break;
597 }
Adis Nezirovic8878f8e2018-07-13 12:18:33 +0200598 }
599
600 lua_settable(L, -3);
601 }
602}
603
604/* Looks in table <t> for a sticky session matching key <key>
605 * Returns table with session data or nil
606 *
607 * The returned table always contains 'use' and 'expire' (integer) fields.
608 * For frequency/rate counters, each data entry is returned as table with
609 * 'value' and 'period' fields.
610 */
611int hlua_stktable_lookup(lua_State *L)
612{
613 struct stktable *t;
614 struct sample smp;
615 struct stktable_key *skey;
616 struct stksess *ts;
617
618 t = hlua_check_stktable(L, 1);
619 smp.data.type = SMP_T_STR;
620 smp.flags = SMP_F_CONST;
Nathan Neulinger31a841c2020-03-03 20:32:47 -0600621 smp.data.u.str.area = (char *)lua_tolstring(L, 2, &smp.data.u.str.data);
Adis Nezirovic8878f8e2018-07-13 12:18:33 +0200622
623 skey = smp_to_stkey(&smp, t);
624 if (!skey) {
625 lua_pushnil(L);
626 return 1;
627 }
628
629 ts = stktable_lookup_key(t, skey);
630 if (!ts) {
631 lua_pushnil(L);
632 return 1;
633 }
634
635 lua_newtable(L);
636 lua_pushstring(L, "use");
637 lua_pushinteger(L, ts->ref_cnt - 1);
638 lua_settable(L, -3);
639
640 lua_pushstring(L, "expire");
641 lua_pushinteger(L, tick_remain(now_ms, ts->expire));
642 lua_settable(L, -3);
643
644 hlua_stktable_entry(L, t, ts);
645 HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
646 ts->ref_cnt--;
647 HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
648
649 return 1;
650}
651
652struct stk_filter {
653 long long val;
654 int type;
655 int op;
656};
657
658
659/* Helper for returning errors to callers using Lua convention (nil, err) */
660static int hlua_error(lua_State *L, const char *fmt, ...) {
661 char buf[256];
662 int len;
663 va_list args;
664 va_start(args, fmt);
665 len = vsnprintf(buf, sizeof(buf), fmt, args);
666 va_end(args);
667
668 if (len < 0) {
669 ha_alert("hlua_error(): Could not write error message.\n");
670 lua_pushnil(L);
671 return 1;
672 } else if (len >= sizeof(buf))
673 ha_alert("hlua_error(): Error message was truncated.\n");
674
675 lua_pushnil(L);
676 lua_pushstring(L, buf);
677
678 return 2;
679}
680
681/* Dump the contents of stick table <t>*/
682int hlua_stktable_dump(lua_State *L)
683{
684 struct stktable *t;
685 struct ebmb_node *eb;
686 struct ebmb_node *n;
687 struct stksess *ts;
688 int type;
689 int op;
690 int dt;
691 long long val;
Adis Nezirovic1a693fc2020-01-16 15:19:29 +0100692 struct stk_filter filter[STKTABLE_FILTER_LEN];
Adis Nezirovic8878f8e2018-07-13 12:18:33 +0200693 int filter_count = 0;
694 int i;
695 int skip_entry;
696 void *ptr;
697
698 t = hlua_check_stktable(L, 1);
699 type = lua_type(L, 2);
700
701 switch (type) {
702 case LUA_TNONE:
703 case LUA_TNIL:
704 break;
705 case LUA_TTABLE:
706 lua_pushnil(L);
707 while (lua_next(L, 2) != 0) {
708 int entry_idx = 0;
709
Adis Nezirovic1a693fc2020-01-16 15:19:29 +0100710 if (filter_count >= STKTABLE_FILTER_LEN)
711 return hlua_error(L, "Filter table too large (len > %d)", STKTABLE_FILTER_LEN);
Adis Nezirovic8878f8e2018-07-13 12:18:33 +0200712
713 if (lua_type(L, -1) != LUA_TTABLE || lua_rawlen(L, -1) != 3)
714 return hlua_error(L, "Filter table entry must be a triplet: {\"data_col\", \"op\", val} (entry #%d)", filter_count + 1);
715
716 lua_pushnil(L);
717 while (lua_next(L, -2) != 0) {
718 switch (entry_idx) {
719 case 0:
720 if (lua_type(L, -1) != LUA_TSTRING)
721 return hlua_error(L, "Filter table data column must be string (entry #%d)", filter_count + 1);
722
723 dt = stktable_get_data_type((char *)lua_tostring(L, -1));
724 if (dt < 0 || t->data_ofs[dt] == 0)
725 return hlua_error(L, "Filter table data column not present in stick table (entry #%d)", filter_count + 1);
726 filter[filter_count].type = dt;
727 break;
728 case 1:
729 if (lua_type(L, -1) != LUA_TSTRING)
730 return hlua_error(L, "Filter table operator must be string (entry #%d)", filter_count + 1);
731
732 op = get_std_op(lua_tostring(L, -1));
733 if (op < 0)
734 return hlua_error(L, "Unknown operator in filter table (entry #%d)", filter_count + 1);
735 filter[filter_count].op = op;
736 break;
737 case 2:
738 val = lua_tointeger(L, -1);
739 filter[filter_count].val = val;
740 filter_count++;
741 break;
742 default:
743 break;
744 }
745 entry_idx++;
746 lua_pop(L, 1);
747 }
748 lua_pop(L, 1);
749 }
750 break;
751 default:
752 return hlua_error(L, "filter table expected");
753 }
754
755 lua_newtable(L);
756
757 HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
758 eb = ebmb_first(&t->keys);
759 for (n = eb; n; n = ebmb_next(n)) {
760 ts = ebmb_entry(n, struct stksess, key);
761 if (!ts) {
762 HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
763 return 1;
764 }
765 ts->ref_cnt++;
766 HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
767
768 /* multi condition/value filter */
769 skip_entry = 0;
770 for (i = 0; i < filter_count; i++) {
771 if (t->data_ofs[filter[i].type] == 0)
772 continue;
773
774 ptr = stktable_data_ptr(t, ts, filter[i].type);
775
776 switch (stktable_data_types[filter[i].type].std_type) {
777 case STD_T_SINT:
778 val = stktable_data_cast(ptr, std_t_sint);
779 break;
780 case STD_T_UINT:
781 val = stktable_data_cast(ptr, std_t_uint);
782 break;
783 case STD_T_ULL:
784 val = stktable_data_cast(ptr, std_t_ull);
785 break;
786 case STD_T_FRQP:
787 val = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
788 t->data_arg[filter[i].type].u);
789 break;
790 default:
791 continue;
792 break;
793 }
794
795 op = filter[i].op;
796
797 if ((val < filter[i].val && (op == STD_OP_EQ || op == STD_OP_GT || op == STD_OP_GE)) ||
798 (val == filter[i].val && (op == STD_OP_NE || op == STD_OP_GT || op == STD_OP_LT)) ||
799 (val > filter[i].val && (op == STD_OP_EQ || op == STD_OP_LT || op == STD_OP_LE))) {
800 skip_entry = 1;
801 break;
802 }
803 }
804
805 if (skip_entry) {
806 HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
807 ts->ref_cnt--;
808 continue;
809 }
810
811 if (t->type == SMP_T_IPV4) {
812 char addr[INET_ADDRSTRLEN];
813 inet_ntop(AF_INET, (const void *)&ts->key.key, addr, sizeof(addr));
814 lua_pushstring(L, addr);
815 } else if (t->type == SMP_T_IPV6) {
816 char addr[INET6_ADDRSTRLEN];
817 inet_ntop(AF_INET6, (const void *)&ts->key.key, addr, sizeof(addr));
818 lua_pushstring(L, addr);
819 } else if (t->type == SMP_T_SINT) {
820 lua_pushinteger(L, *ts->key.key);
821 } else if (t->type == SMP_T_STR) {
822 lua_pushstring(L, (const char *)ts->key.key);
823 } else {
824 return hlua_error(L, "Unsupported stick table key type");
825 }
826
827 lua_newtable(L);
828 hlua_stktable_entry(L, t, ts);
829 lua_settable(L, -3);
830 HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
831 ts->ref_cnt--;
832 }
833 HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
834
835 return 1;
836}
837
Thierry Fournierff480422016-02-25 08:36:46 +0100838int hlua_fcn_new_listener(lua_State *L, struct listener *lst)
839{
840 lua_newtable(L);
841
842 /* Pop a class sesison metatable and affect it to the userdata. */
843 lua_rawgeti(L, LUA_REGISTRYINDEX, class_listener_ref);
844 lua_setmetatable(L, -2);
845
846 lua_pushlightuserdata(L, lst);
847 lua_rawseti(L, -2, 0);
848 return 1;
849}
850
851static struct listener *hlua_check_listener(lua_State *L, int ud)
852{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200853 return hlua_checkudata(L, ud, class_listener_ref);
Thierry Fournierff480422016-02-25 08:36:46 +0100854}
855
856int hlua_listener_get_stats(lua_State *L)
857{
858 struct listener *li;
859 int i;
860
861 li = hlua_check_listener(L, 1);
862
Willy Tarreauc95bad52016-12-22 00:13:31 +0100863 if (!li->bind_conf->frontend) {
Thierry Fournierff480422016-02-25 08:36:46 +0100864 lua_pushnil(L);
865 return 1;
866 }
867
Willy Tarreau708c4162019-10-09 10:19:16 +0200868 stats_fill_li_stats(li->bind_conf->frontend, li, STAT_SHLGNDS, stats, STATS_LEN);
Thierry Fournierff480422016-02-25 08:36:46 +0100869
870 lua_newtable(L);
871 for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
Willy Tarreaueaa55372019-10-09 07:39:11 +0200872 lua_pushstring(L, stat_fields[i].name);
Thierry Fournierff480422016-02-25 08:36:46 +0100873 hlua_fcn_pushfield(L, &stats[i]);
874 lua_settable(L, -3);
875 }
876 return 1;
877
878}
879
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100880int hlua_fcn_new_server(lua_State *L, struct server *srv)
881{
Patrick Hemmera62ae7e2018-04-29 14:23:48 -0400882 char buffer[12];
883
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100884 lua_newtable(L);
885
886 /* Pop a class sesison metatable and affect it to the userdata. */
887 lua_rawgeti(L, LUA_REGISTRYINDEX, class_server_ref);
888 lua_setmetatable(L, -2);
889
890 lua_pushlightuserdata(L, srv);
891 lua_rawseti(L, -2, 0);
Patrick Hemmera62ae7e2018-04-29 14:23:48 -0400892
893 /* Add server name. */
894 lua_pushstring(L, "name");
895 lua_pushstring(L, srv->id);
896 lua_settable(L, -3);
897
898 /* Add server puid. */
899 lua_pushstring(L, "puid");
900 snprintf(buffer, sizeof(buffer), "%d", srv->puid);
901 lua_pushstring(L, buffer);
902 lua_settable(L, -3);
903
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100904 return 1;
905}
906
907static struct server *hlua_check_server(lua_State *L, int ud)
908{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +0200909 return hlua_checkudata(L, ud, class_server_ref);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100910}
911
912int hlua_server_get_stats(lua_State *L)
913{
914 struct server *srv;
915 int i;
916
917 srv = hlua_check_server(L, 1);
918
919 if (!srv->proxy) {
920 lua_pushnil(L);
921 return 1;
922 }
923
Willy Tarreau708c4162019-10-09 10:19:16 +0200924 stats_fill_sv_stats(srv->proxy, srv, STAT_SHLGNDS, stats, STATS_LEN);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100925
926 lua_newtable(L);
927 for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
Willy Tarreaueaa55372019-10-09 07:39:11 +0200928 lua_pushstring(L, stat_fields[i].name);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100929 hlua_fcn_pushfield(L, &stats[i]);
930 lua_settable(L, -3);
931 }
932 return 1;
933
934}
935
936int hlua_server_get_addr(lua_State *L)
937{
938 struct server *srv;
939 char addr[INET6_ADDRSTRLEN];
940 luaL_Buffer b;
941
942 srv = hlua_check_server(L, 1);
943
944 luaL_buffinit(L, &b);
945
946 switch (srv->addr.ss_family) {
947 case AF_INET:
948 inet_ntop(AF_INET, &((struct sockaddr_in *)&srv->addr)->sin_addr,
949 addr, INET_ADDRSTRLEN);
950 luaL_addstring(&b, addr);
951 luaL_addstring(&b, ":");
Nenad Merdanovic38494732017-07-23 22:04:58 -0400952 snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100953 luaL_addstring(&b, addr);
954 break;
955 case AF_INET6:
956 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&srv->addr)->sin6_addr,
Nenad Merdanovica9f04042017-07-23 22:04:59 -0400957 addr, INET6_ADDRSTRLEN);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100958 luaL_addstring(&b, addr);
959 luaL_addstring(&b, ":");
Nenad Merdanovic38494732017-07-23 22:04:58 -0400960 snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +0100961 luaL_addstring(&b, addr);
962 break;
963 case AF_UNIX:
964 luaL_addstring(&b, (char *)((struct sockaddr_un *)&srv->addr)->sun_path);
965 break;
966 default:
967 luaL_addstring(&b, "<unknown>");
968 break;
969 }
970
971 luaL_pushresult(&b);
972 return 1;
973}
974
975int hlua_server_is_draining(lua_State *L)
976{
977 struct server *srv;
978
979 srv = hlua_check_server(L, 1);
980 lua_pushinteger(L, server_is_draining(srv));
981 return 1;
982}
983
Patrick Hemmer32d539f2018-04-29 14:25:46 -0400984int hlua_server_set_maxconn(lua_State *L)
985{
986 struct server *srv;
987 const char *maxconn;
988 const char *err;
989
990 srv = hlua_check_server(L, 1);
991 maxconn = luaL_checkstring(L, 2);
992
993 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
994 err = server_parse_maxconn_change_request(srv, maxconn);
995 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
996 if (!err)
997 lua_pushnil(L);
998 else
999 hlua_pushstrippedstring(L, err);
1000 return 1;
1001}
1002
1003int hlua_server_get_maxconn(lua_State *L)
1004{
1005 struct server *srv;
1006
1007 srv = hlua_check_server(L, 1);
1008 lua_pushinteger(L, srv->maxconn);
1009 return 1;
1010}
1011
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001012int hlua_server_set_weight(lua_State *L)
1013{
1014 struct server *srv;
1015 const char *weight;
1016 const char *err;
1017
1018 srv = hlua_check_server(L, 1);
1019 weight = luaL_checkstring(L, 2);
1020
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001021 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001022 err = server_parse_weight_change_request(srv, weight);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001023 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001024 if (!err)
1025 lua_pushnil(L);
1026 else
1027 hlua_pushstrippedstring(L, err);
1028 return 1;
1029}
1030
1031int hlua_server_get_weight(lua_State *L)
1032{
1033 struct server *srv;
1034
1035 srv = hlua_check_server(L, 1);
1036 lua_pushinteger(L, srv->uweight);
1037 return 1;
1038}
1039
1040int hlua_server_set_addr(lua_State *L)
1041{
1042 struct server *srv;
1043 const char *addr;
Joseph C. Sible49bbf522020-05-04 22:20:32 -04001044 const char *port;
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001045 const char *err;
1046
1047 srv = hlua_check_server(L, 1);
1048 addr = luaL_checkstring(L, 2);
Joseph C. Sible49bbf522020-05-04 22:20:32 -04001049 if (lua_gettop(L) >= 3)
1050 port = luaL_checkstring(L, 3);
1051 else
1052 port = NULL;
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001053
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001054 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
Joseph C. Sible49bbf522020-05-04 22:20:32 -04001055 err = update_server_addr_port(srv, addr, port, "Lua script");
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001056 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001057 if (!err)
1058 lua_pushnil(L);
1059 else
1060 hlua_pushstrippedstring(L, err);
1061 return 1;
1062}
1063
1064int hlua_server_shut_sess(lua_State *L)
1065{
1066 struct server *srv;
1067
1068 srv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001069 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001070 srv_shutdown_streams(srv, SF_ERR_KILLED);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001071 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001072 return 0;
1073}
1074
1075int hlua_server_set_drain(lua_State *L)
1076{
1077 struct server *srv;
1078
1079 srv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001080 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001081 srv_adm_set_drain(srv);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001082 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001083 return 0;
1084}
1085
1086int hlua_server_set_maint(lua_State *L)
1087{
1088 struct server *srv;
1089
1090 srv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001091 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001092 srv_adm_set_maint(srv);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001093 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001094 return 0;
1095}
1096
1097int hlua_server_set_ready(lua_State *L)
1098{
1099 struct server *srv;
1100
1101 srv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001102 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001103 srv_adm_set_ready(srv);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001104 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001105 return 0;
1106}
1107
1108int hlua_server_check_enable(lua_State *L)
1109{
1110 struct server *sv;
1111
1112 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001113 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001114 if (sv->check.state & CHK_ST_CONFIGURED) {
Adis Nezirovicceee9332017-07-26 09:19:06 +02001115 sv->check.state |= CHK_ST_ENABLED;
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001116 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001117 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001118 return 0;
1119}
1120
1121int hlua_server_check_disable(lua_State *L)
1122{
1123 struct server *sv;
1124
1125 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001126 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001127 if (sv->check.state & CHK_ST_CONFIGURED) {
Adis Nezirovicceee9332017-07-26 09:19:06 +02001128 sv->check.state &= ~CHK_ST_ENABLED;
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001129 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001130 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001131 return 0;
1132}
1133
1134int hlua_server_check_force_up(lua_State *L)
1135{
1136 struct server *sv;
1137
1138 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001139 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001140 if (!(sv->track)) {
1141 sv->check.health = sv->check.rise + sv->check.fall - 1;
Emeric Brun5a133512017-10-19 14:42:30 +02001142 srv_set_running(sv, "changed from Lua script", NULL);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001143 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001144 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001145 return 0;
1146}
1147
1148int hlua_server_check_force_nolb(lua_State *L)
1149{
1150 struct server *sv;
1151
1152 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001153 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001154 if (!(sv->track)) {
1155 sv->check.health = sv->check.rise + sv->check.fall - 1;
Emeric Brun5a133512017-10-19 14:42:30 +02001156 srv_set_stopping(sv, "changed from Lua script", NULL);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001157 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001158 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001159 return 0;
1160}
1161
1162int hlua_server_check_force_down(lua_State *L)
1163{
1164 struct server *sv;
1165
1166 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001167 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001168 if (!(sv->track)) {
1169 sv->check.health = 0;
Emeric Brun5a133512017-10-19 14:42:30 +02001170 srv_set_stopped(sv, "changed from Lua script", NULL);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001171 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001172 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001173 return 0;
1174}
1175
1176int hlua_server_agent_enable(lua_State *L)
1177{
1178 struct server *sv;
1179
1180 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001181 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001182 if (sv->agent.state & CHK_ST_CONFIGURED) {
1183 sv->agent.state |= CHK_ST_ENABLED;
1184 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001185 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001186 return 0;
1187}
1188
1189int hlua_server_agent_disable(lua_State *L)
1190{
1191 struct server *sv;
1192
1193 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001194 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001195 if (sv->agent.state & CHK_ST_CONFIGURED) {
1196 sv->agent.state &= ~CHK_ST_ENABLED;
1197 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001198 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001199 return 0;
1200}
1201
1202int hlua_server_agent_force_up(lua_State *L)
1203{
1204 struct server *sv;
1205
1206 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001207 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001208 if (sv->agent.state & CHK_ST_ENABLED) {
1209 sv->agent.health = sv->agent.rise + sv->agent.fall - 1;
Emeric Brun5a133512017-10-19 14:42:30 +02001210 srv_set_running(sv, "changed from Lua script", NULL);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001211 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001212 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001213 return 0;
1214}
1215
1216int hlua_server_agent_force_down(lua_State *L)
1217{
1218 struct server *sv;
1219
1220 sv = hlua_check_server(L, 1);
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001221 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001222 if (sv->agent.state & CHK_ST_ENABLED) {
1223 sv->agent.health = 0;
Emeric Brun5a133512017-10-19 14:42:30 +02001224 srv_set_stopped(sv, "changed from Lua script", NULL);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001225 }
Christopher Faulet2a944ee2017-11-07 10:42:54 +01001226 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001227 return 0;
1228}
1229
Thierry Fournierf61aa632016-02-19 20:56:00 +01001230int hlua_fcn_new_proxy(lua_State *L, struct proxy *px)
1231{
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001232 struct server *srv;
Thierry Fournierff480422016-02-25 08:36:46 +01001233 struct listener *lst;
1234 int lid;
Willy Tarreau29d69802018-05-06 14:50:09 +02001235 char buffer[17];
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001236
Thierry Fournierf61aa632016-02-19 20:56:00 +01001237 lua_newtable(L);
1238
1239 /* Pop a class sesison metatable and affect it to the userdata. */
1240 lua_rawgeti(L, LUA_REGISTRYINDEX, class_proxy_ref);
1241 lua_setmetatable(L, -2);
1242
1243 lua_pushlightuserdata(L, px);
1244 lua_rawseti(L, -2, 0);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001245
Thierry FOURNIERf2bbe382017-07-24 13:59:22 +02001246 /* Add proxy name. */
1247 lua_pushstring(L, "name");
1248 lua_pushstring(L, px->id);
1249 lua_settable(L, -3);
1250
Baptiste Assmann46c72552017-10-26 21:51:58 +02001251 /* Add proxy uuid. */
1252 lua_pushstring(L, "uuid");
1253 snprintf(buffer, sizeof(buffer), "%d", px->uuid);
1254 lua_pushstring(L, buffer);
1255 lua_settable(L, -3);
1256
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001257 /* Browse and register servers. */
1258 lua_pushstring(L, "servers");
1259 lua_newtable(L);
1260 for (srv = px->srv; srv; srv = srv->next) {
1261 lua_pushstring(L, srv->id);
1262 hlua_fcn_new_server(L, srv);
1263 lua_settable(L, -3);
1264 }
1265 lua_settable(L, -3);
1266
Thierry Fournierff480422016-02-25 08:36:46 +01001267 /* Browse and register listeners. */
1268 lua_pushstring(L, "listeners");
1269 lua_newtable(L);
1270 lid = 1;
1271 list_for_each_entry(lst, &px->conf.listeners, by_fe) {
1272 if (lst->name)
1273 lua_pushstring(L, lst->name);
1274 else {
Willy Tarreau29d69802018-05-06 14:50:09 +02001275 snprintf(buffer, sizeof(buffer), "sock-%d", lid);
Thierry Fournierff480422016-02-25 08:36:46 +01001276 lid++;
1277 lua_pushstring(L, buffer);
1278 }
1279 hlua_fcn_new_listener(L, lst);
1280 lua_settable(L, -3);
1281 }
1282 lua_settable(L, -3);
1283
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001284 if (px->table && px->table->id) {
Adis Nezirovic8878f8e2018-07-13 12:18:33 +02001285 lua_pushstring(L, "stktable");
Frédéric Lécaille1b8e68e2019-03-14 07:07:41 +01001286 hlua_fcn_new_stktable(L, px->table);
Adis Nezirovic8878f8e2018-07-13 12:18:33 +02001287 lua_settable(L, -3);
1288 }
1289
Thierry Fournierf61aa632016-02-19 20:56:00 +01001290 return 1;
1291}
1292
1293static struct proxy *hlua_check_proxy(lua_State *L, int ud)
1294{
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001295 return hlua_checkudata(L, ud, class_proxy_ref);
Thierry Fournierf61aa632016-02-19 20:56:00 +01001296}
1297
1298int hlua_proxy_pause(lua_State *L)
1299{
1300 struct proxy *px;
1301
1302 px = hlua_check_proxy(L, 1);
1303 pause_proxy(px);
1304 return 0;
1305}
1306
1307int hlua_proxy_resume(lua_State *L)
1308{
1309 struct proxy *px;
1310
1311 px = hlua_check_proxy(L, 1);
1312 resume_proxy(px);
1313 return 0;
1314}
1315
1316int hlua_proxy_stop(lua_State *L)
1317{
1318 struct proxy *px;
1319
1320 px = hlua_check_proxy(L, 1);
1321 stop_proxy(px);
1322 return 0;
1323}
1324
1325int hlua_proxy_get_cap(lua_State *L)
1326{
1327 struct proxy *px;
1328 const char *str;
1329
1330 px = hlua_check_proxy(L, 1);
1331 str = proxy_cap_str(px->cap);
1332 lua_pushstring(L, str);
1333 return 1;
1334}
1335
1336int hlua_proxy_get_stats(lua_State *L)
1337{
1338 struct proxy *px;
1339 int i;
1340
1341 px = hlua_check_proxy(L, 1);
1342 if (px->cap & PR_CAP_BE)
Willy Tarreau708c4162019-10-09 10:19:16 +02001343 stats_fill_be_stats(px, STAT_SHLGNDS, stats, STATS_LEN);
Thierry Fournierf61aa632016-02-19 20:56:00 +01001344 else
1345 stats_fill_fe_stats(px, stats, STATS_LEN);
1346 lua_newtable(L);
1347 for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
Willy Tarreaueaa55372019-10-09 07:39:11 +02001348 lua_pushstring(L, stat_fields[i].name);
Thierry Fournierf61aa632016-02-19 20:56:00 +01001349 hlua_fcn_pushfield(L, &stats[i]);
1350 lua_settable(L, -3);
1351 }
1352 return 1;
1353}
1354
1355int hlua_proxy_get_mode(lua_State *L)
1356{
1357 struct proxy *px;
1358 const char *str;
1359
1360 px = hlua_check_proxy(L, 1);
1361 str = proxy_mode_str(px->mode);
1362 lua_pushstring(L, str);
1363 return 1;
1364}
1365
1366int hlua_proxy_shut_bcksess(lua_State *L)
1367{
1368 struct proxy *px;
1369
1370 px = hlua_check_proxy(L, 1);
1371 srv_shutdown_backup_streams(px, SF_ERR_KILLED);
1372 return 0;
1373}
1374
Thierry Fournier3d4a6752016-02-19 20:53:30 +01001375int hlua_fcn_post_init(lua_State *L)
1376{
Thierry Fournierf61aa632016-02-19 20:56:00 +01001377 struct proxy *px;
1378
1379 /* get core array. */
1380 if (lua_getglobal(L, "core") != LUA_TTABLE)
1381 lua_error(L);
1382
1383 /* Create proxies entry. */
1384 lua_pushstring(L, "proxies");
1385 lua_newtable(L);
1386
1387 /* List all proxies. */
Olivier Houchardfbc74e82017-11-24 16:54:05 +01001388 for (px = proxies_list; px; px = px->next) {
Thierry Fournierf61aa632016-02-19 20:56:00 +01001389 lua_pushstring(L, px->id);
1390 hlua_fcn_new_proxy(L, px);
1391 lua_settable(L, -3);
1392 }
1393
1394 /* push "proxies" in "core" */
1395 lua_settable(L, -3);
1396
Thierry FOURNIER9b82a582017-07-24 13:30:43 +02001397 /* Create proxies entry. */
1398 lua_pushstring(L, "frontends");
1399 lua_newtable(L);
1400
1401 /* List all proxies. */
Olivier Houchardfbc74e82017-11-24 16:54:05 +01001402 for (px = proxies_list; px; px = px->next) {
Thierry FOURNIER9b82a582017-07-24 13:30:43 +02001403 if (!(px->cap & PR_CAP_FE))
1404 continue;
1405 lua_pushstring(L, px->id);
1406 hlua_fcn_new_proxy(L, px);
1407 lua_settable(L, -3);
1408 }
1409
1410 /* push "frontends" in "core" */
1411 lua_settable(L, -3);
1412
1413 /* Create proxies entry. */
1414 lua_pushstring(L, "backends");
1415 lua_newtable(L);
1416
1417 /* List all proxies. */
Olivier Houchardfbc74e82017-11-24 16:54:05 +01001418 for (px = proxies_list; px; px = px->next) {
Thierry FOURNIER9b82a582017-07-24 13:30:43 +02001419 if (!(px->cap & PR_CAP_BE))
1420 continue;
1421 lua_pushstring(L, px->id);
1422 hlua_fcn_new_proxy(L, px);
1423 lua_settable(L, -3);
1424 }
1425
1426 /* push "backend" in "core" */
1427 lua_settable(L, -3);
1428
Thierry Fournier3d4a6752016-02-19 20:53:30 +01001429 return 1;
1430}
1431
Thierry FOURNIER / OZON.IO8a1027a2016-11-24 20:48:38 +01001432/* This Lua function take a string, a list of separators.
1433 * It tokenize the input string using the list of separators
1434 * as separator.
1435 *
Ilya Shipitsince7b00f2020-03-23 22:28:40 +05001436 * The functionreturns a table filled with tokens.
Thierry FOURNIER / OZON.IO8a1027a2016-11-24 20:48:38 +01001437 */
1438int hlua_tokenize(lua_State *L)
1439{
1440 const char *str;
1441 const char *sep;
1442 int index;
1443 const char *token;
1444 const char *p;
1445 const char *c;
1446 int ignore_empty;
1447
1448 ignore_empty = 0;
1449
1450 str = luaL_checkstring(L, 1);
1451 sep = luaL_checkstring(L, 2);
1452 if (lua_gettop(L) == 3)
1453 ignore_empty = hlua_checkboolean(L, 3);
1454
1455 lua_newtable(L);
1456 index = 1;
1457 token = str;
1458 p = str;
1459 while(1) {
1460 for (c = sep; *c != '\0'; c++)
1461 if (*p == *c)
1462 break;
1463 if (*p == *c) {
1464 if ((!ignore_empty) || (p - token > 0)) {
1465 lua_pushlstring(L, token, p - token);
1466 lua_rawseti(L, -2, index);
1467 index++;
1468 }
1469 token = p + 1;
1470 }
1471 if (*p == '\0')
1472 break;
1473 p++;
1474 }
1475
1476 return 1;
1477}
1478
Thierry FOURNIER / OZON.IO62fec752016-11-10 20:38:11 +01001479int hlua_parse_addr(lua_State *L)
1480{
1481 struct hlua_addr *addr;
1482 const char *str = luaL_checkstring(L, 1);
1483 unsigned char mask;
1484
1485 addr = lua_newuserdata(L, sizeof(struct hlua_addr));
1486 if (!addr) {
1487 lua_pushnil(L);
1488 return 1;
1489 }
1490
1491 if (str2net(str, PAT_MF_NO_DNS, &addr->addr.v4.ip, &addr->addr.v4.mask)) {
1492 addr->type = AF_INET;
1493 return 1;
1494 }
1495
1496 if (str62net(str, &addr->addr.v6.ip, &mask)) {
1497 len2mask6(mask, &addr->addr.v6.mask);
1498 addr->type = AF_INET6;
1499 return 1;
1500 }
1501
1502 lua_pop(L, 1);
1503 lua_pushnil(L);
1504 return 1;
1505}
1506
1507int hlua_match_addr(lua_State *L)
1508{
1509 struct hlua_addr *addr1;
1510 struct hlua_addr *addr2;
1511
1512 if (!lua_isuserdata(L, 1) ||
1513 !lua_isuserdata(L, 2)) {
1514 lua_pushboolean(L, 0);
1515 return 1;
1516 }
1517
1518 addr1 = lua_touserdata(L, 1);
1519 addr2 = lua_touserdata(L, 2);
1520
1521 if (addr1->type != addr2->type) {
1522 lua_pushboolean(L, 0);
1523 return 1;
1524 }
1525
1526 if (addr1->type == AF_INET) {
1527 if ((addr1->addr.v4.ip.s_addr & addr2->addr.v4.mask.s_addr) ==
1528 (addr2->addr.v4.ip.s_addr & addr1->addr.v4.mask.s_addr)) {
1529 lua_pushboolean(L, 1);
1530 return 1;
1531 }
1532 } else {
Thierry FOURNIERde6925e2016-12-23 17:03:25 +01001533 int i;
1534
1535 for (i = 0; i < 16; i += 4) {
Willy Tarreau26474c42020-02-25 10:02:51 +01001536 if ((read_u32(&addr1->addr.v6.ip.s6_addr[i]) &
1537 read_u32(&addr2->addr.v6.mask.s6_addr[i])) !=
1538 (read_u32(&addr2->addr.v6.ip.s6_addr[i]) &
1539 read_u32(&addr1->addr.v6.mask.s6_addr[i])))
Thierry FOURNIERde6925e2016-12-23 17:03:25 +01001540 break;
1541 }
1542 if (i == 16) {
Thierry FOURNIER / OZON.IO62fec752016-11-10 20:38:11 +01001543 lua_pushboolean(L, 1);
1544 return 1;
1545 }
1546 }
1547
1548 lua_pushboolean(L, 0);
1549 return 1;
1550}
1551
Dragan Dosen26743032019-04-30 15:54:36 +02001552static struct my_regex **hlua_check_regex(lua_State *L, int ud)
Thierry FOURNIER31904272017-10-25 12:59:51 +02001553{
1554 return (hlua_checkudata(L, ud, class_regex_ref));
1555}
1556
1557static int hlua_regex_comp(struct lua_State *L)
1558{
Dragan Dosen26743032019-04-30 15:54:36 +02001559 struct my_regex **regex;
Thierry FOURNIER31904272017-10-25 12:59:51 +02001560 const char *str;
1561 int cs;
1562 char *err;
1563
1564 str = luaL_checkstring(L, 1);
1565 luaL_argcheck(L, lua_isboolean(L, 2), 2, NULL);
1566 cs = lua_toboolean(L, 2);
1567
1568 regex = lua_newuserdata(L, sizeof(*regex));
1569
1570 err = NULL;
Dragan Dosen26743032019-04-30 15:54:36 +02001571 if (!(*regex = regex_comp(str, cs, 1, &err))) {
Thierry FOURNIER31904272017-10-25 12:59:51 +02001572 lua_pushboolean(L, 0); /* status error */
1573 lua_pushstring(L, err); /* Reason */
1574 free(err);
1575 return 2;
1576 }
1577
1578 lua_pushboolean(L, 1); /* Status ok */
1579
1580 /* Create object */
1581 lua_newtable(L);
1582 lua_pushvalue(L, -3); /* Get the userdata pointer. */
1583 lua_rawseti(L, -2, 0);
1584 lua_rawgeti(L, LUA_REGISTRYINDEX, class_regex_ref);
1585 lua_setmetatable(L, -2);
1586 return 2;
1587}
1588
1589static int hlua_regex_exec(struct lua_State *L)
1590{
Dragan Dosen26743032019-04-30 15:54:36 +02001591 struct my_regex **regex;
Thierry FOURNIER31904272017-10-25 12:59:51 +02001592 const char *str;
1593 size_t len;
Willy Tarreau83061a82018-07-13 11:56:34 +02001594 struct buffer *tmp;
Thierry FOURNIER31904272017-10-25 12:59:51 +02001595
1596 regex = hlua_check_regex(L, 1);
1597 str = luaL_checklstring(L, 2, &len);
1598
Dragan Dosen26743032019-04-30 15:54:36 +02001599 if (!*regex) {
1600 lua_pushboolean(L, 0);
1601 return 1;
1602 }
1603
Thierry FOURNIER7c210e62017-10-27 14:13:51 +02001604 /* Copy the string because regex_exec2 require a 'char *'
1605 * and not a 'const char *'.
1606 */
1607 tmp = get_trash_chunk();
1608 if (len >= tmp->size) {
1609 lua_pushboolean(L, 0);
1610 return 1;
1611 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001612 memcpy(tmp->area, str, len);
Thierry FOURNIER7c210e62017-10-27 14:13:51 +02001613
Dragan Dosen26743032019-04-30 15:54:36 +02001614 lua_pushboolean(L, regex_exec2(*regex, tmp->area, len));
Thierry FOURNIER31904272017-10-25 12:59:51 +02001615
1616 return 1;
1617}
1618
1619static int hlua_regex_match(struct lua_State *L)
1620{
Dragan Dosen26743032019-04-30 15:54:36 +02001621 struct my_regex **regex;
Thierry FOURNIER31904272017-10-25 12:59:51 +02001622 const char *str;
1623 size_t len;
1624 regmatch_t pmatch[20];
1625 int ret;
1626 int i;
Willy Tarreau83061a82018-07-13 11:56:34 +02001627 struct buffer *tmp;
Thierry FOURNIER31904272017-10-25 12:59:51 +02001628
1629 regex = hlua_check_regex(L, 1);
1630 str = luaL_checklstring(L, 2, &len);
1631
Dragan Dosen26743032019-04-30 15:54:36 +02001632 if (!*regex) {
1633 lua_pushboolean(L, 0);
1634 return 1;
1635 }
1636
Thierry FOURNIER7c210e62017-10-27 14:13:51 +02001637 /* Copy the string because regex_exec2 require a 'char *'
1638 * and not a 'const char *'.
1639 */
1640 tmp = get_trash_chunk();
1641 if (len >= tmp->size) {
1642 lua_pushboolean(L, 0);
1643 return 1;
1644 }
Willy Tarreau843b7cb2018-07-13 10:54:26 +02001645 memcpy(tmp->area, str, len);
Thierry FOURNIER7c210e62017-10-27 14:13:51 +02001646
Dragan Dosen26743032019-04-30 15:54:36 +02001647 ret = regex_exec_match2(*regex, tmp->area, len, 20, pmatch, 0);
Thierry FOURNIER31904272017-10-25 12:59:51 +02001648 lua_pushboolean(L, ret);
1649 lua_newtable(L);
1650 if (ret) {
1651 for (i = 0; i < 20 && pmatch[i].rm_so != -1; i++) {
1652 lua_pushlstring(L, str + pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so);
1653 lua_rawseti(L, -2, i + 1);
1654 }
1655 }
1656 return 2;
1657}
1658
1659static int hlua_regex_free(struct lua_State *L)
1660{
Dragan Dosen26743032019-04-30 15:54:36 +02001661 struct my_regex **regex;
Thierry FOURNIER31904272017-10-25 12:59:51 +02001662
1663 regex = hlua_check_regex(L, 1);
Dragan Dosen26743032019-04-30 15:54:36 +02001664 regex_free(*regex);
1665 *regex = NULL;
Thierry FOURNIER31904272017-10-25 12:59:51 +02001666 return 0;
1667}
1668
Thierry Fournierfb0b5462016-01-21 09:28:58 +01001669int hlua_fcn_reg_core_fcn(lua_State *L)
1670{
Thierry Fournier1de16592016-01-27 09:49:07 +01001671 if (!hlua_concat_init(L))
1672 return 0;
1673
Thierry Fournier4f99b272016-02-22 08:40:02 +01001674 hlua_class_function(L, "now", hlua_now);
1675 hlua_class_function(L, "http_date", hlua_http_date);
1676 hlua_class_function(L, "imf_date", hlua_imf_date);
1677 hlua_class_function(L, "rfc850_date", hlua_rfc850_date);
1678 hlua_class_function(L, "asctime_date", hlua_asctime_date);
1679 hlua_class_function(L, "concat", hlua_concat_new);
Thierry Fourniereea77c02016-03-18 08:47:13 +01001680 hlua_class_function(L, "get_info", hlua_get_info);
Thierry FOURNIER / OZON.IO62fec752016-11-10 20:38:11 +01001681 hlua_class_function(L, "parse_addr", hlua_parse_addr);
1682 hlua_class_function(L, "match_addr", hlua_match_addr);
Thierry FOURNIER / OZON.IO8a1027a2016-11-24 20:48:38 +01001683 hlua_class_function(L, "tokenize", hlua_tokenize);
Thierry Fournier4f99b272016-02-22 08:40:02 +01001684
Thierry FOURNIER31904272017-10-25 12:59:51 +02001685 /* Create regex object. */
1686 lua_newtable(L);
1687 hlua_class_function(L, "new", hlua_regex_comp);
1688
1689 lua_newtable(L); /* The metatable. */
1690 lua_pushstring(L, "__index");
1691 lua_newtable(L);
1692 hlua_class_function(L, "exec", hlua_regex_exec);
1693 hlua_class_function(L, "match", hlua_regex_match);
1694 lua_rawset(L, -3); /* -> META["__index"] = TABLE */
1695 hlua_class_function(L, "__gc", hlua_regex_free);
1696
1697 lua_pushvalue(L, -1); /* Duplicate the metatable reference. */
1698 class_regex_ref = hlua_register_metatable(L, CLASS_REGEX);
1699
1700 lua_setmetatable(L, -2);
1701 lua_setglobal(L, CLASS_REGEX); /* Create global object called Regex */
1702
Adis Nezirovic8878f8e2018-07-13 12:18:33 +02001703 /* Create stktable object. */
1704 lua_newtable(L);
1705 lua_pushstring(L, "__index");
1706 lua_newtable(L);
1707 hlua_class_function(L, "info", hlua_stktable_info);
1708 hlua_class_function(L, "lookup", hlua_stktable_lookup);
1709 hlua_class_function(L, "dump", hlua_stktable_dump);
1710 lua_settable(L, -3); /* -> META["__index"] = TABLE */
1711 class_stktable_ref = hlua_register_metatable(L, CLASS_STKTABLE);
1712
Thierry Fournierff480422016-02-25 08:36:46 +01001713 /* Create listener object. */
1714 lua_newtable(L);
1715 lua_pushstring(L, "__index");
1716 lua_newtable(L);
1717 hlua_class_function(L, "get_stats", hlua_listener_get_stats);
1718 lua_settable(L, -3); /* -> META["__index"] = TABLE */
1719 class_listener_ref = hlua_register_metatable(L, CLASS_LISTENER);
1720
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001721 /* Create server object. */
1722 lua_newtable(L);
1723 lua_pushstring(L, "__index");
1724 lua_newtable(L);
1725 hlua_class_function(L, "is_draining", hlua_server_is_draining);
Patrick Hemmer32d539f2018-04-29 14:25:46 -04001726 hlua_class_function(L, "set_maxconn", hlua_server_set_maxconn);
1727 hlua_class_function(L, "get_maxconn", hlua_server_get_maxconn);
Thierry Fournierf2fdc9d2016-02-22 08:21:39 +01001728 hlua_class_function(L, "set_weight", hlua_server_set_weight);
1729 hlua_class_function(L, "get_weight", hlua_server_get_weight);
1730 hlua_class_function(L, "set_addr", hlua_server_set_addr);
1731 hlua_class_function(L, "get_addr", hlua_server_get_addr);
1732 hlua_class_function(L, "get_stats", hlua_server_get_stats);
1733 hlua_class_function(L, "shut_sess", hlua_server_shut_sess);
1734 hlua_class_function(L, "set_drain", hlua_server_set_drain);
1735 hlua_class_function(L, "set_maint", hlua_server_set_maint);
1736 hlua_class_function(L, "set_ready", hlua_server_set_ready);
1737 hlua_class_function(L, "check_enable", hlua_server_check_enable);
1738 hlua_class_function(L, "check_disable", hlua_server_check_disable);
1739 hlua_class_function(L, "check_force_up", hlua_server_check_force_up);
1740 hlua_class_function(L, "check_force_nolb", hlua_server_check_force_nolb);
1741 hlua_class_function(L, "check_force_down", hlua_server_check_force_down);
1742 hlua_class_function(L, "agent_enable", hlua_server_agent_enable);
1743 hlua_class_function(L, "agent_disable", hlua_server_agent_disable);
1744 hlua_class_function(L, "agent_force_up", hlua_server_agent_force_up);
1745 hlua_class_function(L, "agent_force_down", hlua_server_agent_force_down);
1746 lua_settable(L, -3); /* -> META["__index"] = TABLE */
1747 class_server_ref = hlua_register_metatable(L, CLASS_SERVER);
1748
Thierry Fournierf61aa632016-02-19 20:56:00 +01001749 /* Create proxy object. */
1750 lua_newtable(L);
1751 lua_pushstring(L, "__index");
1752 lua_newtable(L);
1753 hlua_class_function(L, "pause", hlua_proxy_pause);
1754 hlua_class_function(L, "resume", hlua_proxy_resume);
1755 hlua_class_function(L, "stop", hlua_proxy_stop);
1756 hlua_class_function(L, "shut_bcksess", hlua_proxy_shut_bcksess);
1757 hlua_class_function(L, "get_cap", hlua_proxy_get_cap);
1758 hlua_class_function(L, "get_mode", hlua_proxy_get_mode);
1759 hlua_class_function(L, "get_stats", hlua_proxy_get_stats);
1760 lua_settable(L, -3); /* -> META["__index"] = TABLE */
1761 class_proxy_ref = hlua_register_metatable(L, CLASS_PROXY);
1762
Thierry Fournier1550d5d2016-01-21 09:35:41 +01001763 return 5;
Thierry Fournierfb0b5462016-01-21 09:28:58 +01001764}