1 /*
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
13 * 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
18 #define _GNU_SOURCE
19
20 #include <lauxlib.h>
21 #include <lua.h>
22 #include <lualib.h>
23
24 #include <common/time.h>
25 #include <common/uri_auth.h>
26
27 #include <types/cli.h>
28 #include <types/hlua.h>
29 #include <types/proxy.h>
30 #include <types/stats.h>
31
32 #include <proto/proto_http.h>
33 #include <proto/proxy.h>
34 #include <proto/server.h>
35 #include <proto/stats.h>
36
37 /* Contains the class reference of the concat object. */
38 static int class_concat_ref;
39 static int class_proxy_ref;
40 static int class_server_ref;
41 static int class_listener_ref;
42 static int class_regex_ref;
43
44 #define STATS_LEN (MAX((int)ST_F_TOTAL_FIELDS, (int)INF_TOTAL_FIELDS))
45
46 static THREAD_LOCAL struct field stats[STATS_LEN];
47
hlua_checkboolean(lua_State * L,int index)48 int 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
55 /* This function gets a struct field and convert it in Lua
56 * variable. The variable is pushed at the top of the stak.
57 */
hlua_fcn_pushfield(lua_State * L,struct field * field)58 int hlua_fcn_pushfield(lua_State *L, struct field *field)
59 {
60 /* The lua_Integer is always signed. Its length depends on
61 * compilation opions, so the followinfg code is conditionned
62 * by some macros. Windows maros are not supported.
63 * If the number cannot be represented as integer, we try to
64 * convert to float.
65 */
66 switch (field_format(field, 0)) {
67
68 case FF_EMPTY:
69 lua_pushnil(L);
70 return 1;
71
72 case FF_S32:
73 /* S32 is always supported. */
74 lua_pushinteger(L, field->u.s32);
75 return 1;
76
77 case FF_U32:
78 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
79 /* 64 bits case, U32 is always supported */
80 lua_pushinteger(L, field->u.u32);
81 #else
82 /* 32 bits case, U32 is supported until INT_MAX. */
83 if (field->u.u32 > INT_MAX)
84 lua_pushnumber(L, (lua_Number)field->u.u32);
85 else
86 lua_pushinteger(L, field->u.u32);
87 #endif
88 return 1;
89
90 case FF_S64:
91 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
92 /* 64 bits case, S64 is always supported */
93 lua_pushinteger(L, field->u.s64);
94 #else
95 /* 64 bits case, S64 is supported beetween INT_MIN and INT_MAX */
96 if (field->u.s64 < INT_MIN || field->u.s64 > INT_MAX)
97 lua_pushnumber(L, (lua_Number)field->u.s64);
98 else
99 lua_pushinteger(L, (int)field->u.s64);
100 #endif
101 return 1;
102
103 case FF_U64:
104 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
105 /* 64 bits case, U64 is supported until LLONG_MAX */
106 if (field->u.u64 > LLONG_MAX)
107 lua_pushnumber(L, (lua_Number)field->u.u64);
108 else
109 lua_pushinteger(L, field->u.u64);
110 #else
111 /* 64 bits case, U64 is supported until INT_MAX */
112 if (field->u.u64 > INT_MAX)
113 lua_pushnumber(L, (lua_Number)field->u.u64);
114 else
115 lua_pushinteger(L, (int)field->u.u64);
116 #endif
117 return 1;
118
119 case FF_STR:
120 lua_pushstring(L, field->u.str);
121 return 1;
122
123 default:
124 break;
125 }
126
127 /* Default case, never reached. */
128 lua_pushnil(L);
129 return 1;
130 }
131
132 /* Some string are started or terminated by blank chars,
133 * this function removes the spaces, tabs, \r and
134 * \n at the begin and at the end of the string "str", and
135 * push the result in the lua stack.
136 * Returns a pointer to the Lua internal copy of the string.
137 */
hlua_pushstrippedstring(lua_State * L,const char * str)138 const char *hlua_pushstrippedstring(lua_State *L, const char *str)
139 {
140 const char *p;
141 int l;
142
143 for (p = str; HTTP_IS_LWS(*p); p++);
144
145 for (l = strlen(p); l && HTTP_IS_LWS(p[l-1]); l--);
146
147 return lua_pushlstring(L, p, l);
148 }
149
150 /* The three following functions are useful for adding entries
151 * in a table. These functions takes a string and respectively an
152 * integer, a string or a function and add it to the table in the
153 * top of the stack.
154 *
155 * These functions throws an error if no more stack size is
156 * available.
157 */
hlua_class_const_int(lua_State * L,const char * name,int value)158 void hlua_class_const_int(lua_State *L, const char *name, int value)
159 {
160 lua_pushstring(L, name);
161 lua_pushinteger(L, value);
162 lua_rawset(L, -3);
163 }
hlua_class_const_str(lua_State * L,const char * name,const char * value)164 void hlua_class_const_str(lua_State *L, const char *name, const char *value)
165 {
166 lua_pushstring(L, name);
167 lua_pushstring(L, value);
168 lua_rawset(L, -3);
169 }
hlua_class_function(lua_State * L,const char * name,int (* function)(lua_State * L))170 void hlua_class_function(lua_State *L, const char *name, int (*function)(lua_State *L))
171 {
172 lua_pushstring(L, name);
173 lua_pushcclosure(L, function, 0);
174 lua_rawset(L, -3);
175 }
176
177 /* This function returns a string containg the HAProxy object name. */
hlua_dump_object(struct lua_State * L)178 int hlua_dump_object(struct lua_State *L)
179 {
180 const char *name = (const char *)lua_tostring(L, lua_upvalueindex(1));
181 lua_pushfstring(L, "HAProxy class %s", name);
182 return 1;
183 }
184
185 /* This function register a table as metatable and. It names
186 * the metatable, and returns the associated reference.
187 * The original table is poped from the top of the stack.
188 * "name" is the referenced class name.
189 */
hlua_register_metatable(struct lua_State * L,char * name)190 int hlua_register_metatable(struct lua_State *L, char *name)
191 {
192 /* Check the type of the top element. it must be
193 * a table.
194 */
195 if (lua_type(L, -1) != LUA_TTABLE)
196 luaL_error(L, "hlua_register_metatable() requires a type Table "
197 "in the top of the stack");
198
199 /* Add the __tostring function which identify the
200 * created object.
201 */
202 lua_pushstring(L, "__tostring");
203 lua_pushstring(L, name);
204 lua_pushcclosure(L, hlua_dump_object, 1);
205 lua_rawset(L, -3);
206
207 /* Register a named entry for the table. The table
208 * reference is copyed first because the function
209 * lua_setfield() pop the entry.
210 */
211 lua_pushvalue(L, -1);
212 lua_setfield(L, LUA_REGISTRYINDEX, name);
213
214 /* Creates the reference of the object. The
215 * function luaL_ref pop the top of the stack.
216 */
217 return luaL_ref(L, LUA_REGISTRYINDEX);
218 }
219
220 /* Return an object of the expected type, or throws an error. */
hlua_checkudata(lua_State * L,int ud,int class_ref)221 void *hlua_checkudata(lua_State *L, int ud, int class_ref)
222 {
223 void *p;
224 int ret;
225
226 /* Check if the stack entry is an array. */
227 if (!lua_istable(L, ud))
228 luaL_argerror(L, ud, NULL);
229
230 /* pop the metatable of the referencecd object. */
231 if (!lua_getmetatable(L, ud))
232 luaL_argerror(L, ud, NULL);
233
234 /* pop the expected metatable. */
235 lua_rawgeti(L, LUA_REGISTRYINDEX, class_ref);
236
237 /* Check if the metadata have the expected type. */
238 ret = lua_rawequal(L, -1, -2);
239 lua_pop(L, 2);
240 if (!ret)
241 luaL_argerror(L, ud, NULL);
242
243 /* Push on the stack at the entry [0] of the table. */
244 lua_rawgeti(L, ud, 0);
245
246 /* Check if this entry is userdata. */
247 p = lua_touserdata(L, -1);
248 if (!p)
249 luaL_argerror(L, ud, NULL);
250
251 /* Remove the entry returned by lua_rawgeti(). */
252 lua_pop(L, 1);
253
254 /* Return the associated struct. */
255 return p;
256 }
257
258 /* This function return the current date at epoch format in milliseconds. */
hlua_now(lua_State * L)259 int hlua_now(lua_State *L)
260 {
261 lua_newtable(L);
262 lua_pushstring(L, "sec");
263 lua_pushinteger(L, now.tv_sec);
264 lua_rawset(L, -3);
265 lua_pushstring(L, "usec");
266 lua_pushinteger(L, now.tv_usec);
267 lua_rawset(L, -3);
268 return 1;
269 }
270
271 /* This functions expects a Lua string as HTTP date, parse it and
272 * returns an integer containing the epoch format of the date, or
273 * nil if the parsing fails.
274 */
hlua_parse_date(lua_State * L,int (* fcn)(const char *,int,struct tm *))275 static int hlua_parse_date(lua_State *L, int (*fcn)(const char *, int, struct tm*))
276 {
277 const char *str;
278 size_t len;
279 struct tm tm;
280 time_t time;
281
282 str = luaL_checklstring(L, 1, &len);
283
284 if (!fcn(str, len, &tm)) {
285 lua_pushnil(L);
286 return 1;
287 }
288
289 /* This function considers the content of the broken-down time
290 * is exprimed in the UTC timezone. timegm don't care about
291 * the gnu variable tm_gmtoff. If gmtoff is set, or if you know
292 * the timezone from the broken-down time, it must be fixed
293 * after the conversion.
294 */
295 time = my_timegm(&tm);
296 if (time == -1) {
297 lua_pushnil(L);
298 return 1;
299 }
300
301 lua_pushinteger(L, (int)time);
302 return 1;
303 }
hlua_http_date(lua_State * L)304 static int hlua_http_date(lua_State *L)
305 {
306 return hlua_parse_date(L, parse_http_date);
307 }
hlua_imf_date(lua_State * L)308 static int hlua_imf_date(lua_State *L)
309 {
310 return hlua_parse_date(L, parse_imf_date);
311 }
hlua_rfc850_date(lua_State * L)312 static int hlua_rfc850_date(lua_State *L)
313 {
314 return hlua_parse_date(L, parse_rfc850_date);
315 }
hlua_asctime_date(lua_State * L)316 static int hlua_asctime_date(lua_State *L)
317 {
318 return hlua_parse_date(L, parse_asctime_date);
319 }
320
hlua_get_info(lua_State * L)321 static int hlua_get_info(lua_State *L)
322 {
323 int i;
324
325 stats_fill_info(stats, STATS_LEN);
326
327 lua_newtable(L);
328 for (i=0; i<INF_TOTAL_FIELDS; i++) {
329 lua_pushstring(L, info_field_names[i]);
330 hlua_fcn_pushfield(L, &stats[i]);
331 lua_settable(L, -3);
332 }
333 return 1;
334 }
335
hlua_check_concat(lua_State * L,int ud)336 static struct hlua_concat *hlua_check_concat(lua_State *L, int ud)
337 {
338 return (hlua_checkudata(L, ud, class_concat_ref));
339 }
340
hlua_concat_add(lua_State * L)341 static int hlua_concat_add(lua_State *L)
342 {
343 struct hlua_concat *b;
344 char *buffer;
345 char *new;
346 const char *str;
347 size_t l;
348
349 /* First arg must be a concat object. */
350 b = hlua_check_concat(L, 1);
351
352 /* Second arg must be a string. */
353 str = luaL_checklstring(L, 2, &l);
354
355 /* Get the buffer. */
356 lua_rawgeti(L, 1, 1);
357 buffer = lua_touserdata(L, -1);
358 lua_pop(L, 1);
359
360 /* Update the buffer size if it s required. The old buffer
361 * is crushed by the new in the object array, so it will
362 * be deleted by the GC.
363 * Note that in the first loop, the "new" variable is only
364 * used as a flag.
365 */
366 new = NULL;
367 while (b->size - b->len < l) {
368 b->size += HLUA_CONCAT_BLOCSZ;
369 new = buffer;
370 }
371 if (new) {
372 new = lua_newuserdata(L, b->size);
373 memcpy(new, buffer, b->len);
374 lua_rawseti(L, 1, 1);
375 buffer = new;
376 }
377
378 /* Copy string, and update metadata. */
379 memcpy(buffer + b->len, str, l);
380 b->len += l;
381 return 0;
382 }
383
hlua_concat_dump(lua_State * L)384 static int hlua_concat_dump(lua_State *L)
385 {
386 struct hlua_concat *b;
387 char *buffer;
388
389 /* First arg must be a concat object. */
390 b = hlua_check_concat(L, 1);
391
392 /* Get the buffer. */
393 lua_rawgeti(L, 1, 1);
394 buffer = lua_touserdata(L, -1);
395 lua_pop(L, 1);
396
397 /* Push the soncatenated strng in the stack. */
398 lua_pushlstring(L, buffer, b->len);
399 return 1;
400 }
401
hlua_concat_new(lua_State * L)402 int hlua_concat_new(lua_State *L)
403 {
404 struct hlua_concat *b;
405
406 lua_newtable(L);
407 b = lua_newuserdata(L, sizeof(*b));
408 b->size = HLUA_CONCAT_BLOCSZ;
409 b->len = 0;
410 lua_rawseti(L, -2, 0);
411 lua_newuserdata(L, HLUA_CONCAT_BLOCSZ);
412 lua_rawseti(L, -2, 1);
413
414 lua_rawgeti(L, LUA_REGISTRYINDEX, class_concat_ref);
415 lua_setmetatable(L, -2);
416
417 return 1;
418 }
419
concat_tostring(lua_State * L)420 static int concat_tostring(lua_State *L)
421 {
422 const void *ptr = lua_topointer(L, 1);
423 lua_pushfstring(L, "Concat object: %p", ptr);
424 return 1;
425 }
426
hlua_concat_init(lua_State * L)427 static int hlua_concat_init(lua_State *L)
428 {
429 /* Creates the buffered concat object. */
430 lua_newtable(L);
431
432 lua_pushstring(L, "__tostring");
433 lua_pushcclosure(L, concat_tostring, 0);
434 lua_settable(L, -3);
435
436 lua_pushstring(L, "__index"); /* Creates the index entry. */
437 lua_newtable(L); /* The "__index" content. */
438
439 lua_pushstring(L, "add");
440 lua_pushcclosure(L, hlua_concat_add, 0);
441 lua_settable(L, -3);
442
443 lua_pushstring(L, "dump");
444 lua_pushcclosure(L, hlua_concat_dump, 0);
445 lua_settable(L, -3);
446
447 lua_settable(L, -3); /* Sets the __index entry. */
448 class_concat_ref = luaL_ref(L, LUA_REGISTRYINDEX);
449
450 return 1;
451 }
452
hlua_fcn_new_listener(lua_State * L,struct listener * lst)453 int hlua_fcn_new_listener(lua_State *L, struct listener *lst)
454 {
455 lua_newtable(L);
456
457 /* Pop a class sesison metatable and affect it to the userdata. */
458 lua_rawgeti(L, LUA_REGISTRYINDEX, class_listener_ref);
459 lua_setmetatable(L, -2);
460
461 lua_pushlightuserdata(L, lst);
462 lua_rawseti(L, -2, 0);
463 return 1;
464 }
465
hlua_check_listener(lua_State * L,int ud)466 static struct listener *hlua_check_listener(lua_State *L, int ud)
467 {
468 return hlua_checkudata(L, ud, class_listener_ref);
469 }
470
hlua_listener_get_stats(lua_State * L)471 int hlua_listener_get_stats(lua_State *L)
472 {
473 struct listener *li;
474 int i;
475
476 li = hlua_check_listener(L, 1);
477
478 if (!li->bind_conf->frontend) {
479 lua_pushnil(L);
480 return 1;
481 }
482
483 stats_fill_li_stats(li->bind_conf->frontend, li, ST_SHLGNDS, stats, STATS_LEN);
484
485 lua_newtable(L);
486 for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
487 lua_pushstring(L, stat_field_names[i]);
488 hlua_fcn_pushfield(L, &stats[i]);
489 lua_settable(L, -3);
490 }
491 return 1;
492
493 }
494
hlua_fcn_new_server(lua_State * L,struct server * srv)495 int hlua_fcn_new_server(lua_State *L, struct server *srv)
496 {
497 lua_newtable(L);
498
499 /* Pop a class sesison metatable and affect it to the userdata. */
500 lua_rawgeti(L, LUA_REGISTRYINDEX, class_server_ref);
501 lua_setmetatable(L, -2);
502
503 lua_pushlightuserdata(L, srv);
504 lua_rawseti(L, -2, 0);
505 return 1;
506 }
507
hlua_check_server(lua_State * L,int ud)508 static struct server *hlua_check_server(lua_State *L, int ud)
509 {
510 return hlua_checkudata(L, ud, class_server_ref);
511 }
512
hlua_server_get_stats(lua_State * L)513 int hlua_server_get_stats(lua_State *L)
514 {
515 struct server *srv;
516 int i;
517
518 srv = hlua_check_server(L, 1);
519
520 if (!srv->proxy) {
521 lua_pushnil(L);
522 return 1;
523 }
524
525 stats_fill_sv_stats(srv->proxy, srv, ST_SHLGNDS, stats, STATS_LEN);
526
527 lua_newtable(L);
528 for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
529 lua_pushstring(L, stat_field_names[i]);
530 hlua_fcn_pushfield(L, &stats[i]);
531 lua_settable(L, -3);
532 }
533 return 1;
534
535 }
536
hlua_server_get_addr(lua_State * L)537 int hlua_server_get_addr(lua_State *L)
538 {
539 struct server *srv;
540 char addr[INET6_ADDRSTRLEN];
541 luaL_Buffer b;
542
543 srv = hlua_check_server(L, 1);
544
545 luaL_buffinit(L, &b);
546
547 switch (srv->addr.ss_family) {
548 case AF_INET:
549 inet_ntop(AF_INET, &((struct sockaddr_in *)&srv->addr)->sin_addr,
550 addr, INET_ADDRSTRLEN);
551 luaL_addstring(&b, addr);
552 luaL_addstring(&b, ":");
553 snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port);
554 luaL_addstring(&b, addr);
555 break;
556 case AF_INET6:
557 inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&srv->addr)->sin6_addr,
558 addr, INET6_ADDRSTRLEN);
559 luaL_addstring(&b, addr);
560 luaL_addstring(&b, ":");
561 snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port);
562 luaL_addstring(&b, addr);
563 break;
564 case AF_UNIX:
565 luaL_addstring(&b, (char *)((struct sockaddr_un *)&srv->addr)->sun_path);
566 break;
567 default:
568 luaL_addstring(&b, "<unknown>");
569 break;
570 }
571
572 luaL_pushresult(&b);
573 return 1;
574 }
575
hlua_server_is_draining(lua_State * L)576 int hlua_server_is_draining(lua_State *L)
577 {
578 struct server *srv;
579
580 srv = hlua_check_server(L, 1);
581 lua_pushinteger(L, server_is_draining(srv));
582 return 1;
583 }
584
hlua_server_set_weight(lua_State * L)585 int hlua_server_set_weight(lua_State *L)
586 {
587 struct server *srv;
588 const char *weight;
589 const char *err;
590
591 srv = hlua_check_server(L, 1);
592 weight = luaL_checkstring(L, 2);
593
594 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
595 err = server_parse_weight_change_request(srv, weight);
596 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
597 if (!err)
598 lua_pushnil(L);
599 else
600 hlua_pushstrippedstring(L, err);
601 return 1;
602 }
603
hlua_server_get_weight(lua_State * L)604 int hlua_server_get_weight(lua_State *L)
605 {
606 struct server *srv;
607
608 srv = hlua_check_server(L, 1);
609 lua_pushinteger(L, srv->uweight);
610 return 1;
611 }
612
hlua_server_set_addr(lua_State * L)613 int hlua_server_set_addr(lua_State *L)
614 {
615 struct server *srv;
616 const char *addr;
617 const char *err;
618
619 srv = hlua_check_server(L, 1);
620 addr = luaL_checkstring(L, 2);
621
622 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
623 err = server_parse_addr_change_request(srv, addr, "Lua script");
624 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
625 if (!err)
626 lua_pushnil(L);
627 else
628 hlua_pushstrippedstring(L, err);
629 return 1;
630 }
631
hlua_server_shut_sess(lua_State * L)632 int hlua_server_shut_sess(lua_State *L)
633 {
634 struct server *srv;
635
636 srv = hlua_check_server(L, 1);
637 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
638 srv_shutdown_streams(srv, SF_ERR_KILLED);
639 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
640 return 0;
641 }
642
hlua_server_set_drain(lua_State * L)643 int hlua_server_set_drain(lua_State *L)
644 {
645 struct server *srv;
646
647 srv = hlua_check_server(L, 1);
648 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
649 srv_adm_set_drain(srv);
650 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
651 return 0;
652 }
653
hlua_server_set_maint(lua_State * L)654 int hlua_server_set_maint(lua_State *L)
655 {
656 struct server *srv;
657
658 srv = hlua_check_server(L, 1);
659 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
660 srv_adm_set_maint(srv);
661 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
662 return 0;
663 }
664
hlua_server_set_ready(lua_State * L)665 int hlua_server_set_ready(lua_State *L)
666 {
667 struct server *srv;
668
669 srv = hlua_check_server(L, 1);
670 HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
671 srv_adm_set_ready(srv);
672 HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
673 return 0;
674 }
675
hlua_server_check_enable(lua_State * L)676 int hlua_server_check_enable(lua_State *L)
677 {
678 struct server *sv;
679
680 sv = hlua_check_server(L, 1);
681 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
682 if (sv->check.state & CHK_ST_CONFIGURED) {
683 sv->check.state |= CHK_ST_ENABLED;
684 }
685 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
686 return 0;
687 }
688
hlua_server_check_disable(lua_State * L)689 int hlua_server_check_disable(lua_State *L)
690 {
691 struct server *sv;
692
693 sv = hlua_check_server(L, 1);
694 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
695 if (sv->check.state & CHK_ST_CONFIGURED) {
696 sv->check.state &= ~CHK_ST_ENABLED;
697 }
698 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
699 return 0;
700 }
701
hlua_server_check_force_up(lua_State * L)702 int hlua_server_check_force_up(lua_State *L)
703 {
704 struct server *sv;
705
706 sv = hlua_check_server(L, 1);
707 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
708 if (!(sv->track)) {
709 sv->check.health = sv->check.rise + sv->check.fall - 1;
710 srv_set_running(sv, "changed from Lua script", NULL);
711 }
712 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
713 return 0;
714 }
715
hlua_server_check_force_nolb(lua_State * L)716 int hlua_server_check_force_nolb(lua_State *L)
717 {
718 struct server *sv;
719
720 sv = hlua_check_server(L, 1);
721 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
722 if (!(sv->track)) {
723 sv->check.health = sv->check.rise + sv->check.fall - 1;
724 srv_set_stopping(sv, "changed from Lua script", NULL);
725 }
726 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
727 return 0;
728 }
729
hlua_server_check_force_down(lua_State * L)730 int hlua_server_check_force_down(lua_State *L)
731 {
732 struct server *sv;
733
734 sv = hlua_check_server(L, 1);
735 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
736 if (!(sv->track)) {
737 sv->check.health = 0;
738 srv_set_stopped(sv, "changed from Lua script", NULL);
739 }
740 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
741 return 0;
742 }
743
hlua_server_agent_enable(lua_State * L)744 int hlua_server_agent_enable(lua_State *L)
745 {
746 struct server *sv;
747
748 sv = hlua_check_server(L, 1);
749 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
750 if (sv->agent.state & CHK_ST_CONFIGURED) {
751 sv->agent.state |= CHK_ST_ENABLED;
752 }
753 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
754 return 0;
755 }
756
hlua_server_agent_disable(lua_State * L)757 int hlua_server_agent_disable(lua_State *L)
758 {
759 struct server *sv;
760
761 sv = hlua_check_server(L, 1);
762 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
763 if (sv->agent.state & CHK_ST_CONFIGURED) {
764 sv->agent.state &= ~CHK_ST_ENABLED;
765 }
766 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
767 return 0;
768 }
769
hlua_server_agent_force_up(lua_State * L)770 int hlua_server_agent_force_up(lua_State *L)
771 {
772 struct server *sv;
773
774 sv = hlua_check_server(L, 1);
775 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
776 if (sv->agent.state & CHK_ST_ENABLED) {
777 sv->agent.health = sv->agent.rise + sv->agent.fall - 1;
778 srv_set_running(sv, "changed from Lua script", NULL);
779 }
780 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
781 return 0;
782 }
783
hlua_server_agent_force_down(lua_State * L)784 int hlua_server_agent_force_down(lua_State *L)
785 {
786 struct server *sv;
787
788 sv = hlua_check_server(L, 1);
789 HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
790 if (sv->agent.state & CHK_ST_ENABLED) {
791 sv->agent.health = 0;
792 srv_set_stopped(sv, "changed from Lua script", NULL);
793 }
794 HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
795 return 0;
796 }
797
hlua_fcn_new_proxy(lua_State * L,struct proxy * px)798 int hlua_fcn_new_proxy(lua_State *L, struct proxy *px)
799 {
800 struct server *srv;
801 struct listener *lst;
802 int lid;
803 char buffer[17];
804
805 lua_newtable(L);
806
807 /* Pop a class sesison metatable and affect it to the userdata. */
808 lua_rawgeti(L, LUA_REGISTRYINDEX, class_proxy_ref);
809 lua_setmetatable(L, -2);
810
811 lua_pushlightuserdata(L, px);
812 lua_rawseti(L, -2, 0);
813
814 /* Add proxy name. */
815 lua_pushstring(L, "name");
816 lua_pushstring(L, px->id);
817 lua_settable(L, -3);
818
819 /* Add proxy uuid. */
820 lua_pushstring(L, "uuid");
821 snprintf(buffer, sizeof(buffer), "%d", px->uuid);
822 lua_pushstring(L, buffer);
823 lua_settable(L, -3);
824
825 /* Browse and register servers. */
826 lua_pushstring(L, "servers");
827 lua_newtable(L);
828 for (srv = px->srv; srv; srv = srv->next) {
829 lua_pushstring(L, srv->id);
830 hlua_fcn_new_server(L, srv);
831 lua_settable(L, -3);
832 }
833 lua_settable(L, -3);
834
835 /* Browse and register listeners. */
836 lua_pushstring(L, "listeners");
837 lua_newtable(L);
838 lid = 1;
839 list_for_each_entry(lst, &px->conf.listeners, by_fe) {
840 if (lst->name)
841 lua_pushstring(L, lst->name);
842 else {
843 snprintf(buffer, sizeof(buffer), "sock-%d", lid);
844 lid++;
845 lua_pushstring(L, buffer);
846 }
847 hlua_fcn_new_listener(L, lst);
848 lua_settable(L, -3);
849 }
850 lua_settable(L, -3);
851
852 return 1;
853 }
854
hlua_check_proxy(lua_State * L,int ud)855 static struct proxy *hlua_check_proxy(lua_State *L, int ud)
856 {
857 return hlua_checkudata(L, ud, class_proxy_ref);
858 }
859
hlua_proxy_pause(lua_State * L)860 int hlua_proxy_pause(lua_State *L)
861 {
862 struct proxy *px;
863
864 px = hlua_check_proxy(L, 1);
865 pause_proxy(px);
866 return 0;
867 }
868
hlua_proxy_resume(lua_State * L)869 int hlua_proxy_resume(lua_State *L)
870 {
871 struct proxy *px;
872
873 px = hlua_check_proxy(L, 1);
874 resume_proxy(px);
875 return 0;
876 }
877
hlua_proxy_stop(lua_State * L)878 int hlua_proxy_stop(lua_State *L)
879 {
880 struct proxy *px;
881
882 px = hlua_check_proxy(L, 1);
883 stop_proxy(px);
884 return 0;
885 }
886
hlua_proxy_get_cap(lua_State * L)887 int hlua_proxy_get_cap(lua_State *L)
888 {
889 struct proxy *px;
890 const char *str;
891
892 px = hlua_check_proxy(L, 1);
893 str = proxy_cap_str(px->cap);
894 lua_pushstring(L, str);
895 return 1;
896 }
897
hlua_proxy_get_stats(lua_State * L)898 int hlua_proxy_get_stats(lua_State *L)
899 {
900 struct proxy *px;
901 int i;
902
903 px = hlua_check_proxy(L, 1);
904 if (px->cap & PR_CAP_BE)
905 stats_fill_be_stats(px, ST_SHLGNDS, stats, STATS_LEN);
906 else
907 stats_fill_fe_stats(px, stats, STATS_LEN);
908 lua_newtable(L);
909 for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
910 lua_pushstring(L, stat_field_names[i]);
911 hlua_fcn_pushfield(L, &stats[i]);
912 lua_settable(L, -3);
913 }
914 return 1;
915 }
916
hlua_proxy_get_mode(lua_State * L)917 int hlua_proxy_get_mode(lua_State *L)
918 {
919 struct proxy *px;
920 const char *str;
921
922 px = hlua_check_proxy(L, 1);
923 str = proxy_mode_str(px->mode);
924 lua_pushstring(L, str);
925 return 1;
926 }
927
hlua_proxy_shut_bcksess(lua_State * L)928 int hlua_proxy_shut_bcksess(lua_State *L)
929 {
930 struct proxy *px;
931
932 px = hlua_check_proxy(L, 1);
933 srv_shutdown_backup_streams(px, SF_ERR_KILLED);
934 return 0;
935 }
936
hlua_fcn_post_init(lua_State * L)937 int hlua_fcn_post_init(lua_State *L)
938 {
939 struct proxy *px;
940
941 /* get core array. */
942 if (lua_getglobal(L, "core") != LUA_TTABLE)
943 lua_error(L);
944
945 /* Create proxies entry. */
946 lua_pushstring(L, "proxies");
947 lua_newtable(L);
948
949 /* List all proxies. */
950 for (px = proxies_list; px; px = px->next) {
951 lua_pushstring(L, px->id);
952 hlua_fcn_new_proxy(L, px);
953 lua_settable(L, -3);
954 }
955
956 /* push "proxies" in "core" */
957 lua_settable(L, -3);
958
959 /* Create proxies entry. */
960 lua_pushstring(L, "frontends");
961 lua_newtable(L);
962
963 /* List all proxies. */
964 for (px = proxies_list; px; px = px->next) {
965 if (!(px->cap & PR_CAP_FE))
966 continue;
967 lua_pushstring(L, px->id);
968 hlua_fcn_new_proxy(L, px);
969 lua_settable(L, -3);
970 }
971
972 /* push "frontends" in "core" */
973 lua_settable(L, -3);
974
975 /* Create proxies entry. */
976 lua_pushstring(L, "backends");
977 lua_newtable(L);
978
979 /* List all proxies. */
980 for (px = proxies_list; px; px = px->next) {
981 if (!(px->cap & PR_CAP_BE))
982 continue;
983 lua_pushstring(L, px->id);
984 hlua_fcn_new_proxy(L, px);
985 lua_settable(L, -3);
986 }
987
988 /* push "backend" in "core" */
989 lua_settable(L, -3);
990
991 return 1;
992 }
993
994 /* This Lua function take a string, a list of separators.
995 * It tokenize the input string using the list of separators
996 * as separator.
997 *
998 * The functionreturns a tablle filled with tokens.
999 */
hlua_tokenize(lua_State * L)1000 int hlua_tokenize(lua_State *L)
1001 {
1002 const char *str;
1003 const char *sep;
1004 int index;
1005 const char *token;
1006 const char *p;
1007 const char *c;
1008 int ignore_empty;
1009
1010 ignore_empty = 0;
1011
1012 str = luaL_checkstring(L, 1);
1013 sep = luaL_checkstring(L, 2);
1014 if (lua_gettop(L) == 3)
1015 ignore_empty = hlua_checkboolean(L, 3);
1016
1017 lua_newtable(L);
1018 index = 1;
1019 token = str;
1020 p = str;
1021 while(1) {
1022 for (c = sep; *c != '\0'; c++)
1023 if (*p == *c)
1024 break;
1025 if (*p == *c) {
1026 if ((!ignore_empty) || (p - token > 0)) {
1027 lua_pushlstring(L, token, p - token);
1028 lua_rawseti(L, -2, index);
1029 index++;
1030 }
1031 token = p + 1;
1032 }
1033 if (*p == '\0')
1034 break;
1035 p++;
1036 }
1037
1038 return 1;
1039 }
1040
hlua_parse_addr(lua_State * L)1041 int hlua_parse_addr(lua_State *L)
1042 {
1043 struct hlua_addr *addr;
1044 const char *str = luaL_checkstring(L, 1);
1045 unsigned char mask;
1046
1047 addr = lua_newuserdata(L, sizeof(struct hlua_addr));
1048 if (!addr) {
1049 lua_pushnil(L);
1050 return 1;
1051 }
1052
1053 if (str2net(str, PAT_MF_NO_DNS, &addr->addr.v4.ip, &addr->addr.v4.mask)) {
1054 addr->type = AF_INET;
1055 return 1;
1056 }
1057
1058 if (str62net(str, &addr->addr.v6.ip, &mask)) {
1059 len2mask6(mask, &addr->addr.v6.mask);
1060 addr->type = AF_INET6;
1061 return 1;
1062 }
1063
1064 lua_pop(L, 1);
1065 lua_pushnil(L);
1066 return 1;
1067 }
1068
hlua_match_addr(lua_State * L)1069 int hlua_match_addr(lua_State *L)
1070 {
1071 struct hlua_addr *addr1;
1072 struct hlua_addr *addr2;
1073
1074 if (!lua_isuserdata(L, 1) ||
1075 !lua_isuserdata(L, 2)) {
1076 lua_pushboolean(L, 0);
1077 return 1;
1078 }
1079
1080 addr1 = lua_touserdata(L, 1);
1081 addr2 = lua_touserdata(L, 2);
1082
1083 if (addr1->type != addr2->type) {
1084 lua_pushboolean(L, 0);
1085 return 1;
1086 }
1087
1088 if (addr1->type == AF_INET) {
1089 if ((addr1->addr.v4.ip.s_addr & addr2->addr.v4.mask.s_addr) ==
1090 (addr2->addr.v4.ip.s_addr & addr1->addr.v4.mask.s_addr)) {
1091 lua_pushboolean(L, 1);
1092 return 1;
1093 }
1094 } else {
1095 int i;
1096
1097 for (i = 0; i < 16; i += 4) {
1098 if ((*(uint32_t *)&addr1->addr.v6.ip.s6_addr[i] &
1099 *(uint32_t *)&addr2->addr.v6.mask.s6_addr[i]) !=
1100 (*(uint32_t *)&addr2->addr.v6.ip.s6_addr[i] &
1101 *(uint32_t *)&addr1->addr.v6.mask.s6_addr[i]))
1102 break;
1103 }
1104 if (i == 16) {
1105 lua_pushboolean(L, 1);
1106 return 1;
1107 }
1108 }
1109
1110 lua_pushboolean(L, 0);
1111 return 1;
1112 }
1113
hlua_check_regex(lua_State * L,int ud)1114 static struct my_regex *hlua_check_regex(lua_State *L, int ud)
1115 {
1116 return (hlua_checkudata(L, ud, class_regex_ref));
1117 }
1118
hlua_regex_comp(struct lua_State * L)1119 static int hlua_regex_comp(struct lua_State *L)
1120 {
1121 struct my_regex *regex;
1122 const char *str;
1123 int cs;
1124 char *err;
1125
1126 str = luaL_checkstring(L, 1);
1127 luaL_argcheck(L, lua_isboolean(L, 2), 2, NULL);
1128 cs = lua_toboolean(L, 2);
1129
1130 regex = lua_newuserdata(L, sizeof(*regex));
1131
1132 err = NULL;
1133 if (!regex_comp(str, regex, cs, 1, &err)) {
1134 lua_pushboolean(L, 0); /* status error */
1135 lua_pushstring(L, err); /* Reason */
1136 free(err);
1137 return 2;
1138 }
1139
1140 lua_pushboolean(L, 1); /* Status ok */
1141
1142 /* Create object */
1143 lua_newtable(L);
1144 lua_pushvalue(L, -3); /* Get the userdata pointer. */
1145 lua_rawseti(L, -2, 0);
1146 lua_rawgeti(L, LUA_REGISTRYINDEX, class_regex_ref);
1147 lua_setmetatable(L, -2);
1148 return 2;
1149 }
1150
hlua_regex_exec(struct lua_State * L)1151 static int hlua_regex_exec(struct lua_State *L)
1152 {
1153 struct my_regex *regex;
1154 const char *str;
1155 size_t len;
1156 struct chunk *tmp;
1157
1158 regex = hlua_check_regex(L, 1);
1159 str = luaL_checklstring(L, 2, &len);
1160
1161 /* Copy the string because regex_exec2 require a 'char *'
1162 * and not a 'const char *'.
1163 */
1164 tmp = get_trash_chunk();
1165 if (len >= tmp->size) {
1166 lua_pushboolean(L, 0);
1167 return 1;
1168 }
1169 memcpy(tmp->str, str, len);
1170
1171 lua_pushboolean(L, regex_exec2(regex, tmp->str, len));
1172
1173 return 1;
1174 }
1175
hlua_regex_match(struct lua_State * L)1176 static int hlua_regex_match(struct lua_State *L)
1177 {
1178 struct my_regex *regex;
1179 const char *str;
1180 size_t len;
1181 regmatch_t pmatch[20];
1182 int ret;
1183 int i;
1184 struct chunk *tmp;
1185
1186 regex = hlua_check_regex(L, 1);
1187 str = luaL_checklstring(L, 2, &len);
1188
1189 /* Copy the string because regex_exec2 require a 'char *'
1190 * and not a 'const char *'.
1191 */
1192 tmp = get_trash_chunk();
1193 if (len >= tmp->size) {
1194 lua_pushboolean(L, 0);
1195 return 1;
1196 }
1197 memcpy(tmp->str, str, len);
1198
1199 ret = regex_exec_match2(regex, tmp->str, len, 20, pmatch, 0);
1200 lua_pushboolean(L, ret);
1201 lua_newtable(L);
1202 if (ret) {
1203 for (i = 0; i < 20 && pmatch[i].rm_so != -1; i++) {
1204 lua_pushlstring(L, str + pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so);
1205 lua_rawseti(L, -2, i + 1);
1206 }
1207 }
1208 return 2;
1209 }
1210
hlua_regex_free(struct lua_State * L)1211 static int hlua_regex_free(struct lua_State *L)
1212 {
1213 struct my_regex *regex;
1214
1215 regex = hlua_check_regex(L, 1);
1216 regex_free(regex);
1217 return 0;
1218 }
1219
hlua_fcn_reg_core_fcn(lua_State * L)1220 int hlua_fcn_reg_core_fcn(lua_State *L)
1221 {
1222 if (!hlua_concat_init(L))
1223 return 0;
1224
1225 hlua_class_function(L, "now", hlua_now);
1226 hlua_class_function(L, "http_date", hlua_http_date);
1227 hlua_class_function(L, "imf_date", hlua_imf_date);
1228 hlua_class_function(L, "rfc850_date", hlua_rfc850_date);
1229 hlua_class_function(L, "asctime_date", hlua_asctime_date);
1230 hlua_class_function(L, "concat", hlua_concat_new);
1231 hlua_class_function(L, "get_info", hlua_get_info);
1232 hlua_class_function(L, "parse_addr", hlua_parse_addr);
1233 hlua_class_function(L, "match_addr", hlua_match_addr);
1234 hlua_class_function(L, "tokenize", hlua_tokenize);
1235
1236 /* Create regex object. */
1237 lua_newtable(L);
1238 hlua_class_function(L, "new", hlua_regex_comp);
1239
1240 lua_newtable(L); /* The metatable. */
1241 lua_pushstring(L, "__index");
1242 lua_newtable(L);
1243 hlua_class_function(L, "exec", hlua_regex_exec);
1244 hlua_class_function(L, "match", hlua_regex_match);
1245 lua_rawset(L, -3); /* -> META["__index"] = TABLE */
1246 hlua_class_function(L, "__gc", hlua_regex_free);
1247
1248 lua_pushvalue(L, -1); /* Duplicate the metatable reference. */
1249 class_regex_ref = hlua_register_metatable(L, CLASS_REGEX);
1250
1251 lua_setmetatable(L, -2);
1252 lua_setglobal(L, CLASS_REGEX); /* Create global object called Regex */
1253
1254 /* Create listener object. */
1255 lua_newtable(L);
1256 lua_pushstring(L, "__index");
1257 lua_newtable(L);
1258 hlua_class_function(L, "get_stats", hlua_listener_get_stats);
1259 lua_settable(L, -3); /* -> META["__index"] = TABLE */
1260 class_listener_ref = hlua_register_metatable(L, CLASS_LISTENER);
1261
1262 /* Create server object. */
1263 lua_newtable(L);
1264 lua_pushstring(L, "__index");
1265 lua_newtable(L);
1266 hlua_class_function(L, "is_draining", hlua_server_is_draining);
1267 hlua_class_function(L, "set_weight", hlua_server_set_weight);
1268 hlua_class_function(L, "get_weight", hlua_server_get_weight);
1269 hlua_class_function(L, "set_addr", hlua_server_set_addr);
1270 hlua_class_function(L, "get_addr", hlua_server_get_addr);
1271 hlua_class_function(L, "get_stats", hlua_server_get_stats);
1272 hlua_class_function(L, "shut_sess", hlua_server_shut_sess);
1273 hlua_class_function(L, "set_drain", hlua_server_set_drain);
1274 hlua_class_function(L, "set_maint", hlua_server_set_maint);
1275 hlua_class_function(L, "set_ready", hlua_server_set_ready);
1276 hlua_class_function(L, "check_enable", hlua_server_check_enable);
1277 hlua_class_function(L, "check_disable", hlua_server_check_disable);
1278 hlua_class_function(L, "check_force_up", hlua_server_check_force_up);
1279 hlua_class_function(L, "check_force_nolb", hlua_server_check_force_nolb);
1280 hlua_class_function(L, "check_force_down", hlua_server_check_force_down);
1281 hlua_class_function(L, "agent_enable", hlua_server_agent_enable);
1282 hlua_class_function(L, "agent_disable", hlua_server_agent_disable);
1283 hlua_class_function(L, "agent_force_up", hlua_server_agent_force_up);
1284 hlua_class_function(L, "agent_force_down", hlua_server_agent_force_down);
1285 lua_settable(L, -3); /* -> META["__index"] = TABLE */
1286 class_server_ref = hlua_register_metatable(L, CLASS_SERVER);
1287
1288 /* Create proxy object. */
1289 lua_newtable(L);
1290 lua_pushstring(L, "__index");
1291 lua_newtable(L);
1292 hlua_class_function(L, "pause", hlua_proxy_pause);
1293 hlua_class_function(L, "resume", hlua_proxy_resume);
1294 hlua_class_function(L, "stop", hlua_proxy_stop);
1295 hlua_class_function(L, "shut_bcksess", hlua_proxy_shut_bcksess);
1296 hlua_class_function(L, "get_cap", hlua_proxy_get_cap);
1297 hlua_class_function(L, "get_mode", hlua_proxy_get_mode);
1298 hlua_class_function(L, "get_stats", hlua_proxy_get_stats);
1299 lua_settable(L, -3); /* -> META["__index"] = TABLE */
1300 class_proxy_ref = hlua_register_metatable(L, CLASS_PROXY);
1301
1302 return 5;
1303 }
1304