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/proxy.h>
33 #include <proto/server.h>
34 #include <proto/stats.h>
35 #include <proto/stick_table.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 static int class_stktable_ref;
44 
45 #define MAX_STK_FILTER_LEN 4
46 #define STATS_LEN (MAX((int)ST_F_TOTAL_FIELDS, (int)INF_TOTAL_FIELDS))
47 
48 static THREAD_LOCAL struct field stats[STATS_LEN];
49 
hlua_checkboolean(lua_State * L,int index)50 int hlua_checkboolean(lua_State *L, int index)
51 {
52 	if (!lua_isboolean(L, index))
53 		luaL_argerror(L, index, "boolean expected");
54 	return lua_toboolean(L, index);
55 }
56 
57 /* Helper to push unsigned integers to Lua stack, respecting Lua limitations  */
hlua_fcn_pushunsigned(lua_State * L,unsigned int val)58 static int hlua_fcn_pushunsigned(lua_State *L, unsigned int val)
59 {
60 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
61 	lua_pushinteger(L, val);
62 #else
63 	if (val > INT_MAX)
64 		lua_pushnumber(L, (lua_Number)val);
65 	else
66 		lua_pushinteger(L, (int)val);
67 #endif
68 	return 1;
69 }
70 
71 /* Helper to push unsigned long long to Lua stack, respecting Lua limitations  */
hlua_fcn_pushunsigned_ll(lua_State * L,unsigned long long val)72 static int hlua_fcn_pushunsigned_ll(lua_State *L, unsigned long long val) {
73 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
74 	/* 64 bits case, U64 is supported until LLONG_MAX */
75 	if (val > LLONG_MAX)
76 		lua_pushnumber(L, (lua_Number)val);
77 	else
78 		lua_pushinteger(L, val);
79 #else
80 	/* 32 bits case, U64 is supported until INT_MAX */
81 	if (val > INT_MAX)
82 		lua_pushnumber(L, (lua_Number)val);
83 	else
84 		lua_pushinteger(L, (int)val);
85 #endif
86 	return 1;
87 }
88 
89 /* This function gets a struct field and converts it in Lua
90  * variable. The variable is pushed at the top of the stack.
91  */
hlua_fcn_pushfield(lua_State * L,struct field * field)92 int hlua_fcn_pushfield(lua_State *L, struct field *field)
93 {
94 	/* The lua_Integer is always signed. Its length depends on
95 	 * compilation options, so the following code is conditioned
96 	 * by some macros. Windows maros are not supported.
97 	 * If the number cannot be represented as integer, we try to
98 	 * convert to float.
99 	 */
100 	switch (field_format(field, 0)) {
101 
102 	case FF_EMPTY:
103 		lua_pushnil(L);
104 		return 1;
105 
106 	case FF_S32:
107 		/* S32 is always supported. */
108 		lua_pushinteger(L, field->u.s32);
109 		return 1;
110 
111 	case FF_U32:
112 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
113 		/* 64 bits case, U32 is always supported */
114 		lua_pushinteger(L, field->u.u32);
115 #else
116 		/* 32 bits case, U32 is supported until INT_MAX. */
117 		if (field->u.u32 > INT_MAX)
118 			lua_pushnumber(L, (lua_Number)field->u.u32);
119 		else
120 			lua_pushinteger(L, field->u.u32);
121 #endif
122 		return 1;
123 
124 	case FF_S64:
125 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
126 		/* 64 bits case, S64 is always supported */
127 		lua_pushinteger(L, field->u.s64);
128 #else
129 		/* 64 bits case, S64 is supported beetween INT_MIN and INT_MAX */
130 		if (field->u.s64 < INT_MIN || field->u.s64 > INT_MAX)
131 			lua_pushnumber(L, (lua_Number)field->u.s64);
132 		else
133 			lua_pushinteger(L, (int)field->u.s64);
134 #endif
135 		return 1;
136 
137 	case FF_U64:
138 #if (LUA_MAXINTEGER == LLONG_MAX || ((LUA_MAXINTEGER == LONG_MAX) && (__WORDSIZE == 64)))
139 		/* 64 bits case, U64 is supported until LLONG_MAX */
140 		if (field->u.u64 > LLONG_MAX)
141 			lua_pushnumber(L, (lua_Number)field->u.u64);
142 		else
143 			lua_pushinteger(L, field->u.u64);
144 #else
145 		/* 64 bits case, U64 is supported until INT_MAX */
146 		if (field->u.u64 > INT_MAX)
147 			lua_pushnumber(L, (lua_Number)field->u.u64);
148 		else
149 			lua_pushinteger(L, (int)field->u.u64);
150 #endif
151 		return 1;
152 
153 	case FF_STR:
154 		lua_pushstring(L, field->u.str);
155 		return 1;
156 
157 	default:
158 		break;
159 	}
160 
161 	/* Default case, never reached. */
162 	lua_pushnil(L);
163 	return 1;
164 }
165 
166 /* Some string are started or terminated by blank chars,
167  * this function removes the spaces, tabs, \r and
168  * \n at the begin and at the end of the string "str", and
169  * push the result in the lua stack.
170  * Returns a pointer to the Lua internal copy of the string.
171  */
hlua_pushstrippedstring(lua_State * L,const char * str)172 const char *hlua_pushstrippedstring(lua_State *L, const char *str)
173 {
174 	const char *p;
175 	int l;
176 
177 	for (p = str; HTTP_IS_LWS(*p); p++);
178 
179 	for (l = strlen(p); l && HTTP_IS_LWS(p[l-1]); l--);
180 
181 	return lua_pushlstring(L, p, l);
182 }
183 
184 /* The three following functions are useful for adding entries
185  * in a table. These functions takes a string and respectively an
186  * integer, a string or a function and add it to the table in the
187  * top of the stack.
188  *
189  * These functions throws an error if no more stack size is
190  * available.
191  */
hlua_class_const_int(lua_State * L,const char * name,int value)192 void hlua_class_const_int(lua_State *L, const char *name, int value)
193 {
194 	lua_pushstring(L, name);
195 	lua_pushinteger(L, value);
196 	lua_rawset(L, -3);
197 }
hlua_class_const_str(lua_State * L,const char * name,const char * value)198 void hlua_class_const_str(lua_State *L, const char *name, const char *value)
199 {
200 	lua_pushstring(L, name);
201 	lua_pushstring(L, value);
202 	lua_rawset(L, -3);
203 }
hlua_class_function(lua_State * L,const char * name,int (* function)(lua_State * L))204 void hlua_class_function(lua_State *L, const char *name, int (*function)(lua_State *L))
205 {
206 	lua_pushstring(L, name);
207 	lua_pushcclosure(L, function, 0);
208 	lua_rawset(L, -3);
209 }
210 
211 /* This function returns a string containing the HAProxy object name. */
hlua_dump_object(struct lua_State * L)212 int hlua_dump_object(struct lua_State *L)
213 {
214 	const char *name = (const char *)lua_tostring(L, lua_upvalueindex(1));
215 	lua_pushfstring(L, "HAProxy class %s", name);
216 	return 1;
217 }
218 
219 /* This function register a table as metatable and. It names
220  * the metatable, and returns the associated reference.
221  * The original table is poped from the top of the stack.
222  * "name" is the referenced class name.
223  */
hlua_register_metatable(struct lua_State * L,char * name)224 int hlua_register_metatable(struct lua_State *L, char *name)
225 {
226 	/* Check the type of the top element. it must be
227 	 * a table.
228 	 */
229 	if (lua_type(L, -1) != LUA_TTABLE)
230 		luaL_error(L, "hlua_register_metatable() requires a type Table "
231 		              "in the top of the stack");
232 
233 	/* Add the __tostring function which identify the
234 	 * created object.
235 	 */
236 	lua_pushstring(L, "__tostring");
237 	lua_pushstring(L, name);
238 	lua_pushcclosure(L, hlua_dump_object, 1);
239 	lua_rawset(L, -3);
240 
241 	/* Register a named entry for the table. The table
242 	 * reference is copyed first because the function
243 	 * lua_setfield() pop the entry.
244 	 */
245 	lua_pushvalue(L, -1);
246 	lua_setfield(L, LUA_REGISTRYINDEX, name);
247 
248 	/* Creates the reference of the object. The
249 	 * function luaL_ref pop the top of the stack.
250 	 */
251 	return luaL_ref(L, LUA_REGISTRYINDEX);
252 }
253 
254 /* Return an object of the expected type, or throws an error. */
hlua_checkudata(lua_State * L,int ud,int class_ref)255 void *hlua_checkudata(lua_State *L, int ud, int class_ref)
256 {
257 	void *p;
258 	int ret;
259 
260 	/* Check if the stack entry is an array. */
261 	if (!lua_istable(L, ud))
262 		luaL_argerror(L, ud, NULL);
263 
264 	/* pop the metatable of the referencecd object. */
265 	if (!lua_getmetatable(L, ud))
266 		luaL_argerror(L, ud, NULL);
267 
268 	/* pop the expected metatable. */
269 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_ref);
270 
271 	/* Check if the metadata have the expected type. */
272 	ret = lua_rawequal(L, -1, -2);
273 	lua_pop(L, 2);
274 	if (!ret)
275 		luaL_argerror(L, ud, NULL);
276 
277 	/* Push on the stack at the entry [0] of the table. */
278 	lua_rawgeti(L, ud, 0);
279 
280 	/* Check if this entry is userdata. */
281 	p = lua_touserdata(L, -1);
282 	if (!p)
283 		luaL_argerror(L, ud, NULL);
284 
285 	/* Remove the entry returned by lua_rawgeti(). */
286 	lua_pop(L, 1);
287 
288 	/* Return the associated struct. */
289 	return p;
290 }
291 
292 /* This function return the current date at epoch format in milliseconds. */
hlua_now(lua_State * L)293 int hlua_now(lua_State *L)
294 {
295 	lua_newtable(L);
296 	lua_pushstring(L, "sec");
297 	lua_pushinteger(L, now.tv_sec);
298 	lua_rawset(L, -3);
299 	lua_pushstring(L, "usec");
300 	lua_pushinteger(L, now.tv_usec);
301 	lua_rawset(L, -3);
302 	return 1;
303 }
304 
305 /* This functions expects a Lua string as HTTP date, parse it and
306  * returns an integer containing the epoch format of the date, or
307  * nil if the parsing fails.
308  */
hlua_parse_date(lua_State * L,int (* fcn)(const char *,int,struct tm *))309 static int hlua_parse_date(lua_State *L, int (*fcn)(const char *, int, struct tm*))
310 {
311 	const char *str;
312 	size_t len;
313 	struct tm tm;
314 	time_t time;
315 
316 	str = luaL_checklstring(L, 1, &len);
317 
318 	if (!fcn(str, len, &tm)) {
319 		lua_pushnil(L);
320 		return 1;
321 	}
322 
323 	/* This function considers the content of the broken-down time
324 	 * is exprimed in the UTC timezone. timegm don't care about
325 	 * the gnu variable tm_gmtoff. If gmtoff is set, or if you know
326 	 * the timezone from the broken-down time, it must be fixed
327 	 * after the conversion.
328 	 */
329 	time = my_timegm(&tm);
330 	if (time == -1) {
331 		lua_pushnil(L);
332 		return 1;
333 	}
334 
335 	lua_pushinteger(L, (int)time);
336 	return 1;
337 }
hlua_http_date(lua_State * L)338 static int hlua_http_date(lua_State *L)
339 {
340 	return hlua_parse_date(L, parse_http_date);
341 }
hlua_imf_date(lua_State * L)342 static int hlua_imf_date(lua_State *L)
343 {
344 	return hlua_parse_date(L, parse_imf_date);
345 }
hlua_rfc850_date(lua_State * L)346 static int hlua_rfc850_date(lua_State *L)
347 {
348 	return hlua_parse_date(L, parse_rfc850_date);
349 }
hlua_asctime_date(lua_State * L)350 static int hlua_asctime_date(lua_State *L)
351 {
352 	return hlua_parse_date(L, parse_asctime_date);
353 }
354 
hlua_get_info(lua_State * L)355 static int hlua_get_info(lua_State *L)
356 {
357 	int i;
358 
359 	stats_fill_info(stats, STATS_LEN);
360 
361 	lua_newtable(L);
362 	for (i=0; i<INF_TOTAL_FIELDS; i++) {
363 		lua_pushstring(L, info_field_names[i]);
364 		hlua_fcn_pushfield(L, &stats[i]);
365 		lua_settable(L, -3);
366 	}
367 	return 1;
368 }
369 
hlua_check_concat(lua_State * L,int ud)370 static struct hlua_concat *hlua_check_concat(lua_State *L, int ud)
371 {
372 	return (hlua_checkudata(L, ud, class_concat_ref));
373 }
374 
hlua_concat_add(lua_State * L)375 static int hlua_concat_add(lua_State *L)
376 {
377 	struct hlua_concat *b;
378 	char *buffer;
379 	char *new;
380 	const char *str;
381 	size_t l;
382 
383 	/* First arg must be a concat object. */
384 	b = hlua_check_concat(L, 1);
385 
386 	/* Second arg must be a string. */
387 	str = luaL_checklstring(L, 2, &l);
388 
389 	/* Get the buffer. */
390 	lua_rawgeti(L, 1, 1);
391 	buffer = lua_touserdata(L, -1);
392 	lua_pop(L, 1);
393 
394 	/* Update the buffer size if it s required. The old buffer
395 	 * is crushed by the new in the object array, so it will
396 	 * be deleted by the GC.
397 	 * Note that in the first loop, the "new" variable is only
398 	 * used as a flag.
399 	 */
400 	new = NULL;
401 	while (b->size - b->len < l) {
402 		b->size += HLUA_CONCAT_BLOCSZ;
403 		new = buffer;
404 	}
405 	if (new) {
406 		new = lua_newuserdata(L, b->size);
407 		memcpy(new, buffer, b->len);
408 		lua_rawseti(L, 1, 1);
409 		buffer = new;
410 	}
411 
412 	/* Copy string, and update metadata. */
413 	memcpy(buffer + b->len, str, l);
414 	b->len += l;
415 	return 0;
416 }
417 
hlua_concat_dump(lua_State * L)418 static int hlua_concat_dump(lua_State *L)
419 {
420 	struct hlua_concat *b;
421 	char *buffer;
422 
423 	/* First arg must be a concat object. */
424 	b = hlua_check_concat(L, 1);
425 
426 	/* Get the buffer. */
427 	lua_rawgeti(L, 1, 1);
428 	buffer = lua_touserdata(L, -1);
429 	lua_pop(L, 1);
430 
431 	/* Push the soncatenated strng in the stack. */
432 	lua_pushlstring(L, buffer, b->len);
433 	return 1;
434 }
435 
hlua_concat_new(lua_State * L)436 int hlua_concat_new(lua_State *L)
437 {
438 	struct hlua_concat *b;
439 
440 	lua_newtable(L);
441 	b = lua_newuserdata(L, sizeof(*b));
442 	b->size = HLUA_CONCAT_BLOCSZ;
443 	b->len = 0;
444 	lua_rawseti(L, -2, 0);
445 	lua_newuserdata(L, HLUA_CONCAT_BLOCSZ);
446 	lua_rawseti(L, -2, 1);
447 
448 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_concat_ref);
449 	lua_setmetatable(L, -2);
450 
451 	return 1;
452 }
453 
concat_tostring(lua_State * L)454 static int concat_tostring(lua_State *L)
455 {
456 	const void *ptr = lua_topointer(L, 1);
457 	lua_pushfstring(L, "Concat object: %p", ptr);
458 	return 1;
459 }
460 
hlua_concat_init(lua_State * L)461 static int hlua_concat_init(lua_State *L)
462 {
463 	/* Creates the buffered concat object. */
464 	lua_newtable(L);
465 
466 	lua_pushstring(L, "__tostring");
467 	lua_pushcclosure(L, concat_tostring, 0);
468 	lua_settable(L, -3);
469 
470 	lua_pushstring(L, "__index"); /* Creates the index entry. */
471 	lua_newtable(L); /* The "__index" content. */
472 
473 	lua_pushstring(L, "add");
474 	lua_pushcclosure(L, hlua_concat_add, 0);
475 	lua_settable(L, -3);
476 
477 	lua_pushstring(L, "dump");
478 	lua_pushcclosure(L, hlua_concat_dump, 0);
479 	lua_settable(L, -3);
480 
481 	lua_settable(L, -3); /* Sets the __index entry. */
482 	class_concat_ref = luaL_ref(L, LUA_REGISTRYINDEX);
483 
484 	return 1;
485 }
486 
hlua_fcn_new_stktable(lua_State * L,struct stktable * tbl)487 int hlua_fcn_new_stktable(lua_State *L, struct stktable *tbl)
488 {
489 	lua_newtable(L);
490 
491 	/* Pop a class stktbl metatable and affect it to the userdata. */
492 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_stktable_ref);
493 	lua_setmetatable(L, -2);
494 
495 	lua_pushlightuserdata(L, tbl);
496 	lua_rawseti(L, -2, 0);
497 	return 1;
498 }
499 
hlua_check_stktable(lua_State * L,int ud)500 static struct stktable *hlua_check_stktable(lua_State *L, int ud)
501 {
502 	return hlua_checkudata(L, ud, class_stktable_ref);
503 }
504 
505 /* Extract stick table attributes into Lua table */
hlua_stktable_info(lua_State * L)506 int hlua_stktable_info(lua_State *L)
507 {
508 	struct stktable *tbl;
509 	int dt;
510 
511 	tbl = hlua_check_stktable(L, 1);
512 
513 	if (!tbl->id) {
514 		lua_pushnil(L);
515 		return 1;
516 	}
517 
518 	lua_newtable(L);
519 
520 	lua_pushstring(L, "type");
521 	lua_pushstring(L, stktable_types[tbl->type].kw);
522 	lua_settable(L, -3);
523 
524 	lua_pushstring(L, "length");
525 	lua_pushinteger(L, tbl->key_size);
526 	lua_settable(L, -3);
527 
528 	lua_pushstring(L, "size");
529 	hlua_fcn_pushunsigned(L, tbl->size);
530 	lua_settable(L, -3);
531 
532 	lua_pushstring(L, "used");
533 	hlua_fcn_pushunsigned(L, tbl->current);
534 	lua_settable(L, -3);
535 
536 	lua_pushstring(L, "nopurge");
537 	lua_pushboolean(L, tbl->nopurge > 0);
538 	lua_settable(L, -3);
539 
540 	lua_pushstring(L, "expire");
541 	lua_pushinteger(L, tbl->expire);
542 	lua_settable(L, -3);
543 
544 	/* Save data types periods (if applicable) in 'data' table */
545 	lua_pushstring(L, "data");
546 	lua_newtable(L);
547 
548 	for (dt = 0; dt < STKTABLE_DATA_TYPES; dt++) {
549 		if (tbl->data_ofs[dt] == 0)
550 			continue;
551 
552 		lua_pushstring(L, stktable_data_types[dt].name);
553 
554 		if (stktable_data_types[dt].arg_type == ARG_T_DELAY)
555 			lua_pushinteger(L, tbl->data_arg[dt].u);
556 		else
557 			lua_pushinteger(L, -1);
558 
559 		lua_settable(L, -3);
560 	}
561 
562 	lua_settable(L, -3);
563 
564 	return 1;
565 }
566 
567 /* Helper to get extract stick table entry into Lua table */
hlua_stktable_entry(lua_State * L,struct stktable * t,struct stksess * ts)568 static void hlua_stktable_entry(lua_State *L, struct stktable *t, struct stksess *ts)
569 {
570 	int dt;
571 	void *ptr;
572 
573 	for (dt = 0; dt < STKTABLE_DATA_TYPES; dt++) {
574 
575 		if (t->data_ofs[dt] == 0)
576 			continue;
577 
578 		lua_pushstring(L, stktable_data_types[dt].name);
579 
580 		ptr = stktable_data_ptr(t, ts, dt);
581 		switch (stktable_data_types[dt].std_type) {
582 		case STD_T_SINT:
583 			lua_pushinteger(L, stktable_data_cast(ptr, std_t_sint));
584 			break;
585 		case STD_T_UINT:
586 			hlua_fcn_pushunsigned(L, stktable_data_cast(ptr, std_t_uint));
587 			break;
588 		case STD_T_ULL:
589 			hlua_fcn_pushunsigned_ll(L, stktable_data_cast(ptr, std_t_ull));
590 			break;
591 		case STD_T_FRQP:
592 			lua_pushinteger(L, read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
593 			                t->data_arg[dt].u));
594 			break;
595 		case STD_T_DICT: {
596 			struct dict_entry *de;
597 			de = stktable_data_cast(ptr, std_t_dict);
598 			lua_pushstring(L, de ? (char *)de->value.key : "-");
599 			break;
600 		}
601 		}
602 
603 		lua_settable(L, -3);
604 	}
605 }
606 
607 /* Looks in table <t> for a sticky session matching key <key>
608  * Returns table with session data or nil
609  *
610  * The returned table always contains 'use' and 'expire' (integer) fields.
611  * For frequency/rate counters, each data entry is returned as table with
612  * 'value' and 'period' fields.
613  */
hlua_stktable_lookup(lua_State * L)614 int hlua_stktable_lookup(lua_State *L)
615 {
616 	struct stktable *t;
617 	struct sample smp;
618 	struct stktable_key *skey;
619 	struct stksess *ts;
620 
621 	t = hlua_check_stktable(L, 1);
622 	smp.data.type = SMP_T_STR;
623 	smp.flags = SMP_F_CONST;
624 	smp.data.u.str.area = (char *)lua_tolstring(L, 2, &smp.data.u.str.data);
625 
626 	skey = smp_to_stkey(&smp, t);
627 	if (!skey) {
628 		lua_pushnil(L);
629 		return 1;
630 	}
631 
632 	ts = stktable_lookup_key(t, skey);
633 	if (!ts) {
634 		lua_pushnil(L);
635 		return 1;
636 	}
637 
638 	lua_newtable(L);
639 	lua_pushstring(L, "use");
640 	lua_pushinteger(L, ts->ref_cnt - 1);
641 	lua_settable(L, -3);
642 
643 	lua_pushstring(L, "expire");
644 	lua_pushinteger(L, tick_remain(now_ms, ts->expire));
645 	lua_settable(L, -3);
646 
647 	hlua_stktable_entry(L, t, ts);
648 	HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
649 	ts->ref_cnt--;
650 	HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
651 
652 	return 1;
653 }
654 
655 struct stk_filter {
656 	long long val;
657 	int type;
658 	int op;
659 };
660 
661 
662 /* Helper for returning errors to callers using Lua convention (nil, err) */
hlua_error(lua_State * L,const char * fmt,...)663 static int hlua_error(lua_State *L, const char *fmt, ...)  {
664 	char buf[256];
665 	int len;
666 	va_list args;
667 	va_start(args, fmt);
668         len = vsnprintf(buf, sizeof(buf), fmt, args);
669 	va_end(args);
670 
671 	if (len < 0) {
672 		ha_alert("hlua_error(): Could not write error message.\n");
673 		lua_pushnil(L);
674 		return 1;
675 	} else if (len >= sizeof(buf))
676 		ha_alert("hlua_error(): Error message was truncated.\n");
677 
678 	lua_pushnil(L);
679 	lua_pushstring(L, buf);
680 
681 	return 2;
682 }
683 
684 /* Dump the contents of stick table <t>*/
hlua_stktable_dump(lua_State * L)685 int hlua_stktable_dump(lua_State *L)
686 {
687 	struct stktable *t;
688 	struct ebmb_node *eb;
689 	struct ebmb_node *n;
690 	struct stksess *ts;
691 	int type;
692 	int op;
693 	int dt;
694 	long long val;
695 	struct stk_filter filter[MAX_STK_FILTER_LEN];
696 	int filter_count = 0;
697 	int i;
698 	int skip_entry;
699 	void *ptr;
700 
701 	t = hlua_check_stktable(L, 1);
702 	type = lua_type(L, 2);
703 
704 	switch (type) {
705 	case LUA_TNONE:
706 	case LUA_TNIL:
707 		break;
708 	case LUA_TTABLE:
709 		lua_pushnil(L);
710 		while (lua_next(L, 2) != 0) {
711 			int entry_idx = 0;
712 
713 			if (filter_count >= MAX_STK_FILTER_LEN)
714 				return hlua_error(L, "Filter table too large (len > %d)", MAX_STK_FILTER_LEN);
715 
716 			if (lua_type(L, -1) != LUA_TTABLE  || lua_rawlen(L, -1) != 3)
717 				return hlua_error(L, "Filter table entry must be a triplet: {\"data_col\", \"op\", val} (entry #%d)", filter_count + 1);
718 
719 			lua_pushnil(L);
720 			while (lua_next(L, -2) != 0) {
721 				switch (entry_idx) {
722 				case 0:
723 					if (lua_type(L, -1) != LUA_TSTRING)
724 						return hlua_error(L, "Filter table data column must be string (entry #%d)", filter_count + 1);
725 
726 					dt = stktable_get_data_type((char *)lua_tostring(L, -1));
727 					if (dt < 0 || t->data_ofs[dt] == 0)
728 						return hlua_error(L, "Filter table data column not present in stick table (entry #%d)", filter_count + 1);
729 					filter[filter_count].type = dt;
730 					break;
731 				case 1:
732 					if (lua_type(L, -1) != LUA_TSTRING)
733 						return hlua_error(L, "Filter table operator must be string (entry #%d)", filter_count + 1);
734 
735 					op = get_std_op(lua_tostring(L, -1));
736 					if (op < 0)
737 						return hlua_error(L, "Unknown operator in filter table (entry #%d)", filter_count + 1);
738 					filter[filter_count].op = op;
739 					break;
740 				case 2:
741 					val = lua_tointeger(L, -1);
742 					filter[filter_count].val = val;
743 					filter_count++;
744 					break;
745 				default:
746 					break;
747 				}
748 				entry_idx++;
749 				lua_pop(L, 1);
750 			}
751 			lua_pop(L, 1);
752 		}
753 		break;
754 	default:
755 		return hlua_error(L, "filter table expected");
756 	}
757 
758 	lua_newtable(L);
759 
760 	HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
761 	eb = ebmb_first(&t->keys);
762 	for (n = eb; n; n = ebmb_next(n)) {
763 		ts = ebmb_entry(n, struct stksess, key);
764 		if (!ts) {
765 			HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
766 			return 1;
767 		}
768 		ts->ref_cnt++;
769 		HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
770 
771 		/* multi condition/value filter */
772 		skip_entry = 0;
773 		for (i = 0; i < filter_count; i++) {
774 			if (t->data_ofs[filter[i].type] == 0)
775 				continue;
776 
777 			ptr = stktable_data_ptr(t, ts, filter[i].type);
778 
779 			switch (stktable_data_types[filter[i].type].std_type) {
780 			case STD_T_SINT:
781 				val = stktable_data_cast(ptr, std_t_sint);
782 				break;
783 			case STD_T_UINT:
784 				val = stktable_data_cast(ptr, std_t_uint);
785 				break;
786 			case STD_T_ULL:
787 				val = stktable_data_cast(ptr, std_t_ull);
788 				break;
789 			case STD_T_FRQP:
790 				val = read_freq_ctr_period(&stktable_data_cast(ptr, std_t_frqp),
791 						           t->data_arg[filter[i].type].u);
792 				break;
793 			default:
794 				continue;
795 				break;
796 			}
797 
798 			op = filter[i].op;
799 
800 			if ((val < filter[i].val && (op == STD_OP_EQ || op == STD_OP_GT || op == STD_OP_GE)) ||
801 			    (val == filter[i].val && (op == STD_OP_NE || op == STD_OP_GT || op == STD_OP_LT)) ||
802 			    (val > filter[i].val && (op == STD_OP_EQ || op == STD_OP_LT || op == STD_OP_LE))) {
803 				skip_entry = 1;
804 				break;
805 			}
806 		}
807 
808 		if (skip_entry) {
809 			HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
810 			ts->ref_cnt--;
811 			continue;
812 		}
813 
814 		if (t->type == SMP_T_IPV4) {
815 			char addr[INET_ADDRSTRLEN];
816 			inet_ntop(AF_INET, (const void *)&ts->key.key, addr, sizeof(addr));
817 			lua_pushstring(L, addr);
818 		} else if (t->type == SMP_T_IPV6) {
819 			char addr[INET6_ADDRSTRLEN];
820 			inet_ntop(AF_INET6, (const void *)&ts->key.key, addr, sizeof(addr));
821 			lua_pushstring(L, addr);
822 		} else if (t->type == SMP_T_SINT) {
823 			lua_pushinteger(L, *ts->key.key);
824 		} else if (t->type == SMP_T_STR) {
825 			lua_pushstring(L, (const char *)ts->key.key);
826 		} else {
827 			return hlua_error(L, "Unsupported stick table key type");
828 		}
829 
830 		lua_newtable(L);
831 		hlua_stktable_entry(L, t, ts);
832 		lua_settable(L, -3);
833 		HA_SPIN_LOCK(STK_TABLE_LOCK, &t->lock);
834 		ts->ref_cnt--;
835 	}
836 	HA_SPIN_UNLOCK(STK_TABLE_LOCK, &t->lock);
837 
838 	return 1;
839 }
840 
hlua_fcn_new_listener(lua_State * L,struct listener * lst)841 int hlua_fcn_new_listener(lua_State *L, struct listener *lst)
842 {
843 	lua_newtable(L);
844 
845 	/* Pop a class sesison metatable and affect it to the userdata. */
846 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_listener_ref);
847 	lua_setmetatable(L, -2);
848 
849 	lua_pushlightuserdata(L, lst);
850 	lua_rawseti(L, -2, 0);
851 	return 1;
852 }
853 
hlua_check_listener(lua_State * L,int ud)854 static struct listener *hlua_check_listener(lua_State *L, int ud)
855 {
856 	return hlua_checkudata(L, ud, class_listener_ref);
857 }
858 
hlua_listener_get_stats(lua_State * L)859 int hlua_listener_get_stats(lua_State *L)
860 {
861 	struct listener *li;
862 	int i;
863 
864 	li = hlua_check_listener(L, 1);
865 
866 	if (!li->bind_conf->frontend) {
867 		lua_pushnil(L);
868 		return 1;
869 	}
870 
871 	stats_fill_li_stats(li->bind_conf->frontend, li, ST_SHLGNDS, stats, STATS_LEN);
872 
873 	lua_newtable(L);
874 	for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
875 		lua_pushstring(L, stat_field_names[i]);
876 		hlua_fcn_pushfield(L, &stats[i]);
877 		lua_settable(L, -3);
878 	}
879 	return 1;
880 
881 }
882 
hlua_fcn_new_server(lua_State * L,struct server * srv)883 int hlua_fcn_new_server(lua_State *L, struct server *srv)
884 {
885 	char buffer[12];
886 
887 	lua_newtable(L);
888 
889 	/* Pop a class sesison metatable and affect it to the userdata. */
890 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_server_ref);
891 	lua_setmetatable(L, -2);
892 
893 	lua_pushlightuserdata(L, srv);
894 	lua_rawseti(L, -2, 0);
895 
896 	/* Add server name. */
897 	lua_pushstring(L, "name");
898 	lua_pushstring(L, srv->id);
899 	lua_settable(L, -3);
900 
901 	/* Add server puid. */
902 	lua_pushstring(L, "puid");
903 	snprintf(buffer, sizeof(buffer), "%d", srv->puid);
904 	lua_pushstring(L, buffer);
905 	lua_settable(L, -3);
906 
907 	return 1;
908 }
909 
hlua_check_server(lua_State * L,int ud)910 static struct server *hlua_check_server(lua_State *L, int ud)
911 {
912 	return hlua_checkudata(L, ud, class_server_ref);
913 }
914 
hlua_server_get_stats(lua_State * L)915 int hlua_server_get_stats(lua_State *L)
916 {
917 	struct server *srv;
918 	int i;
919 
920 	srv = hlua_check_server(L, 1);
921 
922 	if (!srv->proxy) {
923 		lua_pushnil(L);
924 		return 1;
925 	}
926 
927 	stats_fill_sv_stats(srv->proxy, srv, ST_SHLGNDS, stats, STATS_LEN);
928 
929 	lua_newtable(L);
930 	for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
931 		lua_pushstring(L, stat_field_names[i]);
932 		hlua_fcn_pushfield(L, &stats[i]);
933 		lua_settable(L, -3);
934 	}
935 	return 1;
936 
937 }
938 
hlua_server_get_addr(lua_State * L)939 int hlua_server_get_addr(lua_State *L)
940 {
941 	struct server *srv;
942 	char addr[INET6_ADDRSTRLEN];
943 	luaL_Buffer b;
944 
945 	srv = hlua_check_server(L, 1);
946 
947 	luaL_buffinit(L, &b);
948 
949 	switch (srv->addr.ss_family) {
950 	case AF_INET:
951 		inet_ntop(AF_INET, &((struct sockaddr_in *)&srv->addr)->sin_addr,
952 		          addr, INET_ADDRSTRLEN);
953 		luaL_addstring(&b, addr);
954 		luaL_addstring(&b, ":");
955 		snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port);
956 		luaL_addstring(&b, addr);
957 		break;
958 	case AF_INET6:
959 		inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&srv->addr)->sin6_addr,
960 		          addr, INET6_ADDRSTRLEN);
961 		luaL_addstring(&b, addr);
962 		luaL_addstring(&b, ":");
963 		snprintf(addr, INET_ADDRSTRLEN, "%d", srv->svc_port);
964 		luaL_addstring(&b, addr);
965 		break;
966 	case AF_UNIX:
967 		luaL_addstring(&b, (char *)((struct sockaddr_un *)&srv->addr)->sun_path);
968 		break;
969 	default:
970 		luaL_addstring(&b, "<unknown>");
971 		break;
972 	}
973 
974 	luaL_pushresult(&b);
975 	return 1;
976 }
977 
hlua_server_is_draining(lua_State * L)978 int hlua_server_is_draining(lua_State *L)
979 {
980 	struct server *srv;
981 
982 	srv = hlua_check_server(L, 1);
983 	lua_pushinteger(L, server_is_draining(srv));
984 	return 1;
985 }
986 
hlua_server_set_maxconn(lua_State * L)987 int hlua_server_set_maxconn(lua_State *L)
988 {
989 	struct server *srv;
990 	const char *maxconn;
991 	const char *err;
992 
993 	srv = hlua_check_server(L, 1);
994 	maxconn = luaL_checkstring(L, 2);
995 
996 	HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
997 	err = server_parse_maxconn_change_request(srv, maxconn);
998 	HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
999 	if (!err)
1000 		lua_pushnil(L);
1001 	else
1002 		hlua_pushstrippedstring(L, err);
1003 	return 1;
1004 }
1005 
hlua_server_get_maxconn(lua_State * L)1006 int hlua_server_get_maxconn(lua_State *L)
1007 {
1008 	struct server *srv;
1009 
1010 	srv = hlua_check_server(L, 1);
1011 	lua_pushinteger(L, srv->maxconn);
1012 	return 1;
1013 }
1014 
hlua_server_set_weight(lua_State * L)1015 int hlua_server_set_weight(lua_State *L)
1016 {
1017 	struct server *srv;
1018 	const char *weight;
1019 	const char *err;
1020 
1021 	srv = hlua_check_server(L, 1);
1022 	weight = luaL_checkstring(L, 2);
1023 
1024 	HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
1025 	err = server_parse_weight_change_request(srv, weight);
1026 	HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1027 	if (!err)
1028 		lua_pushnil(L);
1029 	else
1030 		hlua_pushstrippedstring(L, err);
1031 	return 1;
1032 }
1033 
hlua_server_get_weight(lua_State * L)1034 int hlua_server_get_weight(lua_State *L)
1035 {
1036 	struct server *srv;
1037 
1038 	srv = hlua_check_server(L, 1);
1039 	lua_pushinteger(L, srv->uweight);
1040 	return 1;
1041 }
1042 
hlua_server_set_addr(lua_State * L)1043 int hlua_server_set_addr(lua_State *L)
1044 {
1045 	struct server *srv;
1046 	const char *addr;
1047 	const char *err;
1048 
1049 	srv = hlua_check_server(L, 1);
1050 	addr = luaL_checkstring(L, 2);
1051 
1052 	HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
1053 	err = server_parse_addr_change_request(srv, addr, "Lua script");
1054 	HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1055 	if (!err)
1056 		lua_pushnil(L);
1057 	else
1058 		hlua_pushstrippedstring(L, err);
1059 	return 1;
1060 }
1061 
hlua_server_shut_sess(lua_State * L)1062 int hlua_server_shut_sess(lua_State *L)
1063 {
1064 	struct server *srv;
1065 
1066 	srv = hlua_check_server(L, 1);
1067 	HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
1068 	srv_shutdown_streams(srv, SF_ERR_KILLED);
1069 	HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1070 	return 0;
1071 }
1072 
hlua_server_set_drain(lua_State * L)1073 int hlua_server_set_drain(lua_State *L)
1074 {
1075 	struct server *srv;
1076 
1077 	srv = hlua_check_server(L, 1);
1078 	HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
1079 	srv_adm_set_drain(srv);
1080 	HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1081 	return 0;
1082 }
1083 
hlua_server_set_maint(lua_State * L)1084 int hlua_server_set_maint(lua_State *L)
1085 {
1086 	struct server *srv;
1087 
1088 	srv = hlua_check_server(L, 1);
1089 	HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
1090 	srv_adm_set_maint(srv);
1091 	HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1092 	return 0;
1093 }
1094 
hlua_server_set_ready(lua_State * L)1095 int hlua_server_set_ready(lua_State *L)
1096 {
1097 	struct server *srv;
1098 
1099 	srv = hlua_check_server(L, 1);
1100 	HA_SPIN_LOCK(SERVER_LOCK, &srv->lock);
1101 	srv_adm_set_ready(srv);
1102 	HA_SPIN_UNLOCK(SERVER_LOCK, &srv->lock);
1103 	return 0;
1104 }
1105 
hlua_server_check_enable(lua_State * L)1106 int hlua_server_check_enable(lua_State *L)
1107 {
1108 	struct server *sv;
1109 
1110 	sv = hlua_check_server(L, 1);
1111 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1112 	if (sv->check.state & CHK_ST_CONFIGURED) {
1113 		sv->check.state |= CHK_ST_ENABLED;
1114 	}
1115 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1116 	return 0;
1117 }
1118 
hlua_server_check_disable(lua_State * L)1119 int hlua_server_check_disable(lua_State *L)
1120 {
1121 	struct server *sv;
1122 
1123 	sv = hlua_check_server(L, 1);
1124 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1125 	if (sv->check.state & CHK_ST_CONFIGURED) {
1126 		sv->check.state &= ~CHK_ST_ENABLED;
1127 	}
1128 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1129 	return 0;
1130 }
1131 
hlua_server_check_force_up(lua_State * L)1132 int hlua_server_check_force_up(lua_State *L)
1133 {
1134 	struct server *sv;
1135 
1136 	sv = hlua_check_server(L, 1);
1137 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1138 	if (!(sv->track)) {
1139 		sv->check.health = sv->check.rise + sv->check.fall - 1;
1140 		srv_set_running(sv, "changed from Lua script", NULL);
1141 	}
1142 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1143 	return 0;
1144 }
1145 
hlua_server_check_force_nolb(lua_State * L)1146 int hlua_server_check_force_nolb(lua_State *L)
1147 {
1148 	struct server *sv;
1149 
1150 	sv = hlua_check_server(L, 1);
1151 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1152 	if (!(sv->track)) {
1153 		sv->check.health = sv->check.rise + sv->check.fall - 1;
1154 		srv_set_stopping(sv, "changed from Lua script", NULL);
1155 	}
1156 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1157 	return 0;
1158 }
1159 
hlua_server_check_force_down(lua_State * L)1160 int hlua_server_check_force_down(lua_State *L)
1161 {
1162 	struct server *sv;
1163 
1164 	sv = hlua_check_server(L, 1);
1165 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1166 	if (!(sv->track)) {
1167 		sv->check.health = 0;
1168 		srv_set_stopped(sv, "changed from Lua script", NULL);
1169 	}
1170 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1171 	return 0;
1172 }
1173 
hlua_server_agent_enable(lua_State * L)1174 int hlua_server_agent_enable(lua_State *L)
1175 {
1176 	struct server *sv;
1177 
1178 	sv = hlua_check_server(L, 1);
1179 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1180 	if (sv->agent.state & CHK_ST_CONFIGURED) {
1181 		sv->agent.state |= CHK_ST_ENABLED;
1182 	}
1183 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1184 	return 0;
1185 }
1186 
hlua_server_agent_disable(lua_State * L)1187 int hlua_server_agent_disable(lua_State *L)
1188 {
1189 	struct server *sv;
1190 
1191 	sv = hlua_check_server(L, 1);
1192 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1193 	if (sv->agent.state & CHK_ST_CONFIGURED) {
1194 		sv->agent.state &= ~CHK_ST_ENABLED;
1195 	}
1196 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1197 	return 0;
1198 }
1199 
hlua_server_agent_force_up(lua_State * L)1200 int hlua_server_agent_force_up(lua_State *L)
1201 {
1202 	struct server *sv;
1203 
1204 	sv = hlua_check_server(L, 1);
1205 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1206 	if (sv->agent.state & CHK_ST_ENABLED) {
1207 		sv->agent.health = sv->agent.rise + sv->agent.fall - 1;
1208 		srv_set_running(sv, "changed from Lua script", NULL);
1209 	}
1210 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1211 	return 0;
1212 }
1213 
hlua_server_agent_force_down(lua_State * L)1214 int hlua_server_agent_force_down(lua_State *L)
1215 {
1216 	struct server *sv;
1217 
1218 	sv = hlua_check_server(L, 1);
1219 	HA_SPIN_LOCK(SERVER_LOCK, &sv->lock);
1220 	if (sv->agent.state & CHK_ST_ENABLED) {
1221 		sv->agent.health = 0;
1222 		srv_set_stopped(sv, "changed from Lua script", NULL);
1223 	}
1224 	HA_SPIN_UNLOCK(SERVER_LOCK, &sv->lock);
1225 	return 0;
1226 }
1227 
hlua_fcn_new_proxy(lua_State * L,struct proxy * px)1228 int hlua_fcn_new_proxy(lua_State *L, struct proxy *px)
1229 {
1230 	struct server *srv;
1231 	struct listener *lst;
1232 	int lid;
1233 	char buffer[17];
1234 
1235 	lua_newtable(L);
1236 
1237 	/* Pop a class sesison metatable and affect it to the userdata. */
1238 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_proxy_ref);
1239 	lua_setmetatable(L, -2);
1240 
1241 	lua_pushlightuserdata(L, px);
1242 	lua_rawseti(L, -2, 0);
1243 
1244 	/* Add proxy name. */
1245 	lua_pushstring(L, "name");
1246 	lua_pushstring(L, px->id);
1247 	lua_settable(L, -3);
1248 
1249 	/* Add proxy uuid. */
1250 	lua_pushstring(L, "uuid");
1251 	snprintf(buffer, sizeof(buffer), "%d", px->uuid);
1252 	lua_pushstring(L, buffer);
1253 	lua_settable(L, -3);
1254 
1255 	/* Browse and register servers. */
1256 	lua_pushstring(L, "servers");
1257 	lua_newtable(L);
1258 	for (srv = px->srv; srv; srv = srv->next) {
1259 		lua_pushstring(L, srv->id);
1260 		hlua_fcn_new_server(L, srv);
1261 		lua_settable(L, -3);
1262 	}
1263 	lua_settable(L, -3);
1264 
1265 	/* Browse and register listeners. */
1266 	lua_pushstring(L, "listeners");
1267 	lua_newtable(L);
1268 	lid = 1;
1269 	list_for_each_entry(lst, &px->conf.listeners, by_fe) {
1270 		if (lst->name)
1271 			lua_pushstring(L, lst->name);
1272 		else {
1273 			snprintf(buffer, sizeof(buffer), "sock-%d", lid);
1274 			lid++;
1275 			lua_pushstring(L, buffer);
1276 		}
1277 		hlua_fcn_new_listener(L, lst);
1278 		lua_settable(L, -3);
1279 	}
1280 	lua_settable(L, -3);
1281 
1282 	if (px->table && px->table->id) {
1283 		lua_pushstring(L, "stktable");
1284 		hlua_fcn_new_stktable(L, px->table);
1285 		lua_settable(L, -3);
1286 	}
1287 
1288 	return 1;
1289 }
1290 
hlua_check_proxy(lua_State * L,int ud)1291 static struct proxy *hlua_check_proxy(lua_State *L, int ud)
1292 {
1293 	return hlua_checkudata(L, ud, class_proxy_ref);
1294 }
1295 
hlua_proxy_pause(lua_State * L)1296 int hlua_proxy_pause(lua_State *L)
1297 {
1298 	struct proxy *px;
1299 
1300 	px = hlua_check_proxy(L, 1);
1301 	pause_proxy(px);
1302 	return 0;
1303 }
1304 
hlua_proxy_resume(lua_State * L)1305 int hlua_proxy_resume(lua_State *L)
1306 {
1307 	struct proxy *px;
1308 
1309 	px = hlua_check_proxy(L, 1);
1310 	resume_proxy(px);
1311 	return 0;
1312 }
1313 
hlua_proxy_stop(lua_State * L)1314 int hlua_proxy_stop(lua_State *L)
1315 {
1316 	struct proxy *px;
1317 
1318 	px = hlua_check_proxy(L, 1);
1319 	stop_proxy(px);
1320 	return 0;
1321 }
1322 
hlua_proxy_get_cap(lua_State * L)1323 int hlua_proxy_get_cap(lua_State *L)
1324 {
1325 	struct proxy *px;
1326 	const char *str;
1327 
1328 	px = hlua_check_proxy(L, 1);
1329 	str = proxy_cap_str(px->cap);
1330 	lua_pushstring(L, str);
1331 	return 1;
1332 }
1333 
hlua_proxy_get_stats(lua_State * L)1334 int hlua_proxy_get_stats(lua_State *L)
1335 {
1336 	struct proxy *px;
1337 	int i;
1338 
1339 	px = hlua_check_proxy(L, 1);
1340 	if (px->cap & PR_CAP_BE)
1341 		stats_fill_be_stats(px, ST_SHLGNDS, stats, STATS_LEN);
1342 	else
1343 		stats_fill_fe_stats(px, stats, STATS_LEN);
1344 	lua_newtable(L);
1345 	for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
1346 		lua_pushstring(L, stat_field_names[i]);
1347 		hlua_fcn_pushfield(L, &stats[i]);
1348 		lua_settable(L, -3);
1349 	}
1350 	return 1;
1351 }
1352 
hlua_proxy_get_mode(lua_State * L)1353 int hlua_proxy_get_mode(lua_State *L)
1354 {
1355 	struct proxy *px;
1356 	const char *str;
1357 
1358 	px = hlua_check_proxy(L, 1);
1359 	str = proxy_mode_str(px->mode);
1360 	lua_pushstring(L, str);
1361 	return 1;
1362 }
1363 
hlua_proxy_shut_bcksess(lua_State * L)1364 int hlua_proxy_shut_bcksess(lua_State *L)
1365 {
1366 	struct proxy *px;
1367 
1368 	px = hlua_check_proxy(L, 1);
1369 	srv_shutdown_backup_streams(px, SF_ERR_KILLED);
1370 	return 0;
1371 }
1372 
hlua_fcn_post_init(lua_State * L)1373 int hlua_fcn_post_init(lua_State *L)
1374 {
1375 	struct proxy *px;
1376 
1377 	/* get core array. */
1378 	if (lua_getglobal(L, "core") != LUA_TTABLE)
1379 		lua_error(L);
1380 
1381 	/* Create proxies entry. */
1382 	lua_pushstring(L, "proxies");
1383 	lua_newtable(L);
1384 
1385 	/* List all proxies. */
1386 	for (px = proxies_list; px; px = px->next) {
1387 		lua_pushstring(L, px->id);
1388 		hlua_fcn_new_proxy(L, px);
1389 		lua_settable(L, -3);
1390 	}
1391 
1392 	/* push "proxies" in "core" */
1393 	lua_settable(L, -3);
1394 
1395 	/* Create proxies entry. */
1396 	lua_pushstring(L, "frontends");
1397 	lua_newtable(L);
1398 
1399 	/* List all proxies. */
1400 	for (px = proxies_list; px; px = px->next) {
1401 		if (!(px->cap & PR_CAP_FE))
1402 			continue;
1403 		lua_pushstring(L, px->id);
1404 		hlua_fcn_new_proxy(L, px);
1405 		lua_settable(L, -3);
1406 	}
1407 
1408 	/* push "frontends" in "core" */
1409 	lua_settable(L, -3);
1410 
1411 	/* Create proxies entry. */
1412 	lua_pushstring(L, "backends");
1413 	lua_newtable(L);
1414 
1415 	/* List all proxies. */
1416 	for (px = proxies_list; px; px = px->next) {
1417 		if (!(px->cap & PR_CAP_BE))
1418 			continue;
1419 		lua_pushstring(L, px->id);
1420 		hlua_fcn_new_proxy(L, px);
1421 		lua_settable(L, -3);
1422 	}
1423 
1424 	/* push "backend" in "core" */
1425 	lua_settable(L, -3);
1426 
1427 	return 1;
1428 }
1429 
1430 /* This Lua function take a string, a list of separators.
1431  * It tokenize the input string using the list of separators
1432  * as separator.
1433  *
1434  * The functionreturns a tablle filled with tokens.
1435  */
hlua_tokenize(lua_State * L)1436 int hlua_tokenize(lua_State *L)
1437 {
1438 	const char *str;
1439 	const char *sep;
1440 	int index;
1441 	const char *token;
1442 	const char *p;
1443 	const char *c;
1444 	int ignore_empty;
1445 
1446 	ignore_empty = 0;
1447 
1448 	str = luaL_checkstring(L, 1);
1449 	sep = luaL_checkstring(L, 2);
1450 	if (lua_gettop(L) == 3)
1451 		ignore_empty = hlua_checkboolean(L, 3);
1452 
1453 	lua_newtable(L);
1454 	index = 1;
1455 	token = str;
1456 	p = str;
1457 	while(1) {
1458 		for (c = sep; *c != '\0'; c++)
1459 			if (*p == *c)
1460 				break;
1461 		if (*p == *c) {
1462 			if ((!ignore_empty) || (p - token > 0)) {
1463 				lua_pushlstring(L, token, p - token);
1464 				lua_rawseti(L, -2, index);
1465 				index++;
1466 			}
1467 			token = p + 1;
1468 		}
1469 		if (*p == '\0')
1470 			break;
1471 		p++;
1472 	}
1473 
1474 	return 1;
1475 }
1476 
hlua_parse_addr(lua_State * L)1477 int hlua_parse_addr(lua_State *L)
1478 {
1479 	struct hlua_addr *addr;
1480 	const char *str = luaL_checkstring(L, 1);
1481 	unsigned char mask;
1482 
1483 	addr = lua_newuserdata(L, sizeof(struct hlua_addr));
1484 	if (!addr) {
1485 		lua_pushnil(L);
1486 		return 1;
1487 	}
1488 
1489 	if (str2net(str, PAT_MF_NO_DNS, &addr->addr.v4.ip, &addr->addr.v4.mask)) {
1490 		addr->type = AF_INET;
1491 		return 1;
1492 	}
1493 
1494 	if (str62net(str, &addr->addr.v6.ip, &mask)) {
1495 		len2mask6(mask, &addr->addr.v6.mask);
1496 		addr->type = AF_INET6;
1497 		return 1;
1498 	}
1499 
1500 	lua_pop(L, 1);
1501 	lua_pushnil(L);
1502 	return 1;
1503 }
1504 
hlua_match_addr(lua_State * L)1505 int hlua_match_addr(lua_State *L)
1506 {
1507 	struct hlua_addr *addr1;
1508 	struct hlua_addr *addr2;
1509 
1510 	if (!lua_isuserdata(L, 1) ||
1511 	    !lua_isuserdata(L, 2)) {
1512 		lua_pushboolean(L, 0);
1513 		return 1;
1514 	}
1515 
1516 	addr1 = lua_touserdata(L, 1);
1517 	addr2 = lua_touserdata(L, 2);
1518 
1519 	if (addr1->type != addr2->type) {
1520 		lua_pushboolean(L, 0);
1521 		return 1;
1522 	}
1523 
1524 	if (addr1->type == AF_INET) {
1525 		if ((addr1->addr.v4.ip.s_addr & addr2->addr.v4.mask.s_addr) ==
1526 		    (addr2->addr.v4.ip.s_addr & addr1->addr.v4.mask.s_addr)) {
1527 			lua_pushboolean(L, 1);
1528 			return 1;
1529 		}
1530 	} else {
1531 		int i;
1532 
1533 		for (i = 0; i < 16; i += 4) {
1534 			if ((*(uint32_t *)&addr1->addr.v6.ip.s6_addr[i] &
1535 			     *(uint32_t *)&addr2->addr.v6.mask.s6_addr[i]) !=
1536 			    (*(uint32_t *)&addr2->addr.v6.ip.s6_addr[i] &
1537 			     *(uint32_t *)&addr1->addr.v6.mask.s6_addr[i]))
1538 				break;
1539 		}
1540 		if (i == 16) {
1541 			lua_pushboolean(L, 1);
1542 			return 1;
1543 		}
1544 	}
1545 
1546 	lua_pushboolean(L, 0);
1547 	return 1;
1548 }
1549 
hlua_check_regex(lua_State * L,int ud)1550 static struct my_regex **hlua_check_regex(lua_State *L, int ud)
1551 {
1552 	return (hlua_checkudata(L, ud, class_regex_ref));
1553 }
1554 
hlua_regex_comp(struct lua_State * L)1555 static int hlua_regex_comp(struct lua_State *L)
1556 {
1557 	struct my_regex **regex;
1558 	const char *str;
1559 	int cs;
1560 	char *err;
1561 
1562 	str = luaL_checkstring(L, 1);
1563 	luaL_argcheck(L, lua_isboolean(L, 2), 2, NULL);
1564 	cs = lua_toboolean(L, 2);
1565 
1566 	regex = lua_newuserdata(L, sizeof(*regex));
1567 
1568 	err = NULL;
1569 	if (!(*regex = regex_comp(str, cs, 1, &err))) {
1570 		lua_pushboolean(L, 0); /* status error */
1571 		lua_pushstring(L, err); /* Reason */
1572 		free(err);
1573 		return 2;
1574 	}
1575 
1576 	lua_pushboolean(L, 1); /* Status ok */
1577 
1578 	/* Create object */
1579 	lua_newtable(L);
1580 	lua_pushvalue(L, -3); /* Get the userdata pointer. */
1581 	lua_rawseti(L, -2, 0);
1582 	lua_rawgeti(L, LUA_REGISTRYINDEX, class_regex_ref);
1583 	lua_setmetatable(L, -2);
1584 	return 2;
1585 }
1586 
hlua_regex_exec(struct lua_State * L)1587 static int hlua_regex_exec(struct lua_State *L)
1588 {
1589 	struct my_regex **regex;
1590 	const char *str;
1591 	size_t len;
1592 	struct buffer *tmp;
1593 
1594 	regex = hlua_check_regex(L, 1);
1595 	str = luaL_checklstring(L, 2, &len);
1596 
1597 	if (!*regex) {
1598 		lua_pushboolean(L, 0);
1599 		return 1;
1600 	}
1601 
1602 	/* Copy the string because regex_exec2 require a 'char *'
1603 	 * and not a 'const char *'.
1604 	 */
1605 	tmp = get_trash_chunk();
1606 	if (len >= tmp->size) {
1607 		lua_pushboolean(L, 0);
1608 		return 1;
1609 	}
1610 	memcpy(tmp->area, str, len);
1611 
1612 	lua_pushboolean(L, regex_exec2(*regex, tmp->area, len));
1613 
1614 	return 1;
1615 }
1616 
hlua_regex_match(struct lua_State * L)1617 static int hlua_regex_match(struct lua_State *L)
1618 {
1619 	struct my_regex **regex;
1620 	const char *str;
1621 	size_t len;
1622 	regmatch_t pmatch[20];
1623 	int ret;
1624 	int i;
1625 	struct buffer *tmp;
1626 
1627 	regex = hlua_check_regex(L, 1);
1628 	str = luaL_checklstring(L, 2, &len);
1629 
1630 	if (!*regex) {
1631 		lua_pushboolean(L, 0);
1632 		return 1;
1633 	}
1634 
1635 	/* Copy the string because regex_exec2 require a 'char *'
1636 	 * and not a 'const char *'.
1637 	 */
1638 	tmp = get_trash_chunk();
1639 	if (len >= tmp->size) {
1640 		lua_pushboolean(L, 0);
1641 		return 1;
1642 	}
1643 	memcpy(tmp->area, str, len);
1644 
1645 	ret = regex_exec_match2(*regex, tmp->area, len, 20, pmatch, 0);
1646 	lua_pushboolean(L, ret);
1647 	lua_newtable(L);
1648 	if (ret) {
1649 		for (i = 0; i < 20 && pmatch[i].rm_so != -1; i++) {
1650 			lua_pushlstring(L, str + pmatch[i].rm_so, pmatch[i].rm_eo - pmatch[i].rm_so);
1651 			lua_rawseti(L, -2, i + 1);
1652 		}
1653 	}
1654 	return 2;
1655 }
1656 
hlua_regex_free(struct lua_State * L)1657 static int hlua_regex_free(struct lua_State *L)
1658 {
1659 	struct my_regex **regex;
1660 
1661 	regex = hlua_check_regex(L, 1);
1662 	regex_free(*regex);
1663 	*regex = NULL;
1664 	return 0;
1665 }
1666 
hlua_fcn_reg_core_fcn(lua_State * L)1667 int hlua_fcn_reg_core_fcn(lua_State *L)
1668 {
1669 	if (!hlua_concat_init(L))
1670 		return 0;
1671 
1672 	hlua_class_function(L, "now", hlua_now);
1673 	hlua_class_function(L, "http_date", hlua_http_date);
1674 	hlua_class_function(L, "imf_date", hlua_imf_date);
1675 	hlua_class_function(L, "rfc850_date", hlua_rfc850_date);
1676 	hlua_class_function(L, "asctime_date", hlua_asctime_date);
1677 	hlua_class_function(L, "concat", hlua_concat_new);
1678 	hlua_class_function(L, "get_info", hlua_get_info);
1679 	hlua_class_function(L, "parse_addr", hlua_parse_addr);
1680 	hlua_class_function(L, "match_addr", hlua_match_addr);
1681 	hlua_class_function(L, "tokenize", hlua_tokenize);
1682 
1683 	/* Create regex object. */
1684 	lua_newtable(L);
1685 	hlua_class_function(L, "new", hlua_regex_comp);
1686 
1687 	lua_newtable(L); /* The metatable. */
1688 	lua_pushstring(L, "__index");
1689 	lua_newtable(L);
1690 	hlua_class_function(L, "exec", hlua_regex_exec);
1691 	hlua_class_function(L, "match", hlua_regex_match);
1692 	lua_rawset(L, -3); /* -> META["__index"] = TABLE */
1693 	hlua_class_function(L, "__gc", hlua_regex_free);
1694 
1695 	lua_pushvalue(L, -1); /* Duplicate the metatable reference. */
1696 	class_regex_ref = hlua_register_metatable(L, CLASS_REGEX);
1697 
1698 	lua_setmetatable(L, -2);
1699 	lua_setglobal(L, CLASS_REGEX); /* Create global object called Regex */
1700 
1701 	/* Create stktable object. */
1702 	lua_newtable(L);
1703 	lua_pushstring(L, "__index");
1704 	lua_newtable(L);
1705 	hlua_class_function(L, "info", hlua_stktable_info);
1706 	hlua_class_function(L, "lookup", hlua_stktable_lookup);
1707 	hlua_class_function(L, "dump", hlua_stktable_dump);
1708 	lua_settable(L, -3); /* -> META["__index"] = TABLE */
1709 	class_stktable_ref = hlua_register_metatable(L, CLASS_STKTABLE);
1710 
1711 	/* Create listener object. */
1712 	lua_newtable(L);
1713 	lua_pushstring(L, "__index");
1714 	lua_newtable(L);
1715 	hlua_class_function(L, "get_stats", hlua_listener_get_stats);
1716 	lua_settable(L, -3); /* -> META["__index"] = TABLE */
1717 	class_listener_ref = hlua_register_metatable(L, CLASS_LISTENER);
1718 
1719 	/* Create server object. */
1720 	lua_newtable(L);
1721 	lua_pushstring(L, "__index");
1722 	lua_newtable(L);
1723 	hlua_class_function(L, "is_draining", hlua_server_is_draining);
1724 	hlua_class_function(L, "set_maxconn", hlua_server_set_maxconn);
1725 	hlua_class_function(L, "get_maxconn", hlua_server_get_maxconn);
1726 	hlua_class_function(L, "set_weight", hlua_server_set_weight);
1727 	hlua_class_function(L, "get_weight", hlua_server_get_weight);
1728 	hlua_class_function(L, "set_addr", hlua_server_set_addr);
1729 	hlua_class_function(L, "get_addr", hlua_server_get_addr);
1730 	hlua_class_function(L, "get_stats", hlua_server_get_stats);
1731 	hlua_class_function(L, "shut_sess", hlua_server_shut_sess);
1732 	hlua_class_function(L, "set_drain", hlua_server_set_drain);
1733 	hlua_class_function(L, "set_maint", hlua_server_set_maint);
1734 	hlua_class_function(L, "set_ready", hlua_server_set_ready);
1735 	hlua_class_function(L, "check_enable", hlua_server_check_enable);
1736 	hlua_class_function(L, "check_disable", hlua_server_check_disable);
1737 	hlua_class_function(L, "check_force_up", hlua_server_check_force_up);
1738 	hlua_class_function(L, "check_force_nolb", hlua_server_check_force_nolb);
1739 	hlua_class_function(L, "check_force_down", hlua_server_check_force_down);
1740 	hlua_class_function(L, "agent_enable", hlua_server_agent_enable);
1741 	hlua_class_function(L, "agent_disable", hlua_server_agent_disable);
1742 	hlua_class_function(L, "agent_force_up", hlua_server_agent_force_up);
1743 	hlua_class_function(L, "agent_force_down", hlua_server_agent_force_down);
1744 	lua_settable(L, -3); /* -> META["__index"] = TABLE */
1745 	class_server_ref = hlua_register_metatable(L, CLASS_SERVER);
1746 
1747 	/* Create proxy object. */
1748 	lua_newtable(L);
1749 	lua_pushstring(L, "__index");
1750 	lua_newtable(L);
1751 	hlua_class_function(L, "pause", hlua_proxy_pause);
1752 	hlua_class_function(L, "resume", hlua_proxy_resume);
1753 	hlua_class_function(L, "stop", hlua_proxy_stop);
1754 	hlua_class_function(L, "shut_bcksess", hlua_proxy_shut_bcksess);
1755 	hlua_class_function(L, "get_cap", hlua_proxy_get_cap);
1756 	hlua_class_function(L, "get_mode", hlua_proxy_get_mode);
1757 	hlua_class_function(L, "get_stats", hlua_proxy_get_stats);
1758 	lua_settable(L, -3); /* -> META["__index"] = TABLE */
1759 	class_proxy_ref = hlua_register_metatable(L, CLASS_PROXY);
1760 
1761 	return 5;
1762 }
1763