aboutsummaryrefslogtreecommitdiff
path: root/src/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/options.c')
-rw-r--r--src/options.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/options.c b/src/options.c
new file mode 100644
index 0000000..32a98d6
--- /dev/null
+++ b/src/options.c
@@ -0,0 +1,137 @@
1#include <lauxlib.h>
2#include <string.h>
3
4#include "auxiliar.h"
5#include "options.h"
6
7static int opt_setmembership(lua_State *L, p_sock ps, int level, int name);
8static int opt_setboolean(lua_State *L, p_sock ps, int level, int name);
9static int opt_set(lua_State *L, p_sock ps, int level, int name,
10 void *val, int len);
11
12/*=========================================================================*\
13* Exported functions
14\*=========================================================================*/
15/*-------------------------------------------------------------------------*\
16* Calls appropriate option handler
17\*-------------------------------------------------------------------------*/
18int opt_meth_setoption(lua_State *L, p_opt opt, p_sock ps)
19{
20 const char *name = luaL_checkstring(L, 2); /* obj, name, ... */
21 while (opt->name && strcmp(name, opt->name))
22 opt++;
23 if (!opt->func) {
24 char msg[45];
25 sprintf(msg, "unsupported option `%.35s'", name);
26 luaL_argerror(L, 2, msg);
27 }
28 return opt->func(L, ps);
29}
30
31/* enables reuse of local address */
32int opt_reuseaddr(lua_State *L, p_sock ps)
33{
34 return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
35}
36
37/* disables the Naggle algorithm */
38int opt_tcp_nodelay(lua_State *L, p_sock ps)
39{
40 return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
41}
42
43int opt_keepalive(lua_State *L, p_sock ps)
44{
45 return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
46}
47
48int opt_dontroute(lua_State *L, p_sock ps)
49{
50 return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
51}
52
53int opt_broadcast(lua_State *L, p_sock ps)
54{
55 return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
56}
57
58int opt_ip_multicast_loop(lua_State *L, p_sock ps)
59{
60 return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP);
61}
62
63int opt_linger(lua_State *L, p_sock ps)
64{
65 struct linger li; /* obj, name, table */
66 if (!lua_istable(L, 3)) luaL_typerror(L, 3, lua_typename(L, LUA_TTABLE));
67 lua_pushstring(L, "on");
68 lua_gettable(L, 3);
69 if (!lua_isboolean(L, -1))
70 luaL_argerror(L, 3, "boolean 'on' field expected");
71 li.l_onoff = lua_toboolean(L, -1);
72 lua_pushstring(L, "timeout");
73 lua_gettable(L, 3);
74 if (!lua_isnumber(L, -1))
75 luaL_argerror(L, 3, "number 'timeout' field expected");
76 li.l_linger = (int) lua_tonumber(L, -1);
77 return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li));
78}
79
80int opt_ip_multicast_ttl(lua_State *L, p_sock ps)
81{
82 int val = (int) luaL_checknumber(L, 3); /* obj, name, int */
83 return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &val, sizeof(val));
84}
85
86int opt_ip_add_membership(lua_State *L, p_sock ps)
87{
88 return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP);
89}
90
91int opt_ip_drop_membersip(lua_State *L, p_sock ps)
92{
93 return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP);
94}
95
96/*=========================================================================*\
97* Auxiliar functions
98\*=========================================================================*/
99static int opt_setmembership(lua_State *L, p_sock ps, int level, int name)
100{
101 struct ip_mreq val; /* obj, name, table */
102 if (!lua_istable(L, 3)) luaL_typerror(L, 3, lua_typename(L, LUA_TTABLE));
103 lua_pushstring(L, "multiaddr");
104 lua_gettable(L, 3);
105 if (!lua_isstring(L, -1))
106 luaL_argerror(L, 3, "string 'multiaddr' field expected");
107 if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr))
108 luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
109 lua_pushstring(L, "interface");
110 lua_gettable(L, 3);
111 if (!lua_isstring(L, -1))
112 luaL_argerror(L, 3, "string 'interface' field expected");
113 val.imr_interface.s_addr = htonl(INADDR_ANY);
114 if (strcmp(lua_tostring(L, -1), "*") &&
115 !inet_aton(lua_tostring(L, -1), &val.imr_interface))
116 luaL_argerror(L, 3, "invalid 'interface' ip address");
117 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
118}
119
120static
121int opt_set(lua_State *L, p_sock ps, int level, int name, void *val, int len)
122{
123 if (setsockopt(*ps, level, name, (char *) val, len) < 0) {
124 lua_pushnil(L);
125 lua_pushstring(L, "setsockopt failed");
126 return 2;
127 }
128 lua_pushnumber(L, 1);
129 return 1;
130}
131
132static int opt_setboolean(lua_State *L, p_sock ps, int level, int name)
133{
134 int val = aux_checkboolean(L, 3); /* obj, name, bool */
135 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
136}
137