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