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