aboutsummaryrefslogtreecommitdiff
path: root/src/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/options.c')
-rw-r--r--src/options.c135
1 files changed, 123 insertions, 12 deletions
diff --git a/src/options.c b/src/options.c
index 6f36ba4..8737d9c 100644
--- a/src/options.c
+++ b/src/options.c
@@ -3,6 +3,9 @@
3* LuaSocket toolkit 3* LuaSocket toolkit
4\*=========================================================================*/ 4\*=========================================================================*/
5#include <string.h> 5#include <string.h>
6#include <sys/types.h>
7#include <sys/socket.h>
8#include <net/if.h>
6 9
7#include "lauxlib.h" 10#include "lauxlib.h"
8 11
@@ -10,12 +13,30 @@
10#include "options.h" 13#include "options.h"
11#include "inet.h" 14#include "inet.h"
12 15
16/* Some platforms use IPV6_JOIN_GROUP instead if
17 * IPV6_ADD_MEMBERSHIP. The semantics are same, though. */
18#ifndef IPV6_ADD_MEMBERSHIP
19#ifdef IPV6_JOIN_GROUP
20#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
21#endif /* IPV6_JOIN_GROUP */
22#endif /* !IPV6_ADD_MEMBERSHIP */
23
24/* Same with IPV6_DROP_MEMBERSHIP / IPV6_LEAVE_GROUP. */
25#ifndef IPV6_DROP_MEMBERSHIP
26#ifdef IPV6_LEAVE_GROUP
27#define IPV6_DROP_MEMBERSHIP IPV6_LEAVE_GROUP
28#endif /* IPV6_LEAVE_GROUP */
29#endif /* !IPV6_DROP_MEMBERSHIP */
30
13/*=========================================================================*\ 31/*=========================================================================*\
14* Internal functions prototypes 32* Internal functions prototypes
15\*=========================================================================*/ 33\*=========================================================================*/
16static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); 34static int opt_setmembership(lua_State *L, p_socket ps, int level, int name);
35static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name);
17static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); 36static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
18static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); 37static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
38static int opt_setint(lua_State *L, p_socket ps, int level, int name);
39static int opt_getint(lua_State *L, p_socket ps, int level, int name);
19static int opt_set(lua_State *L, p_socket ps, int level, int name, 40static int opt_set(lua_State *L, p_socket ps, int level, int name,
20 void *val, int len); 41 void *val, int len);
21static int opt_get(lua_State *L, p_socket ps, int level, int name, 42static int opt_get(lua_State *L, p_socket ps, int level, int name,
@@ -106,6 +127,26 @@ int opt_set_broadcast(lua_State *L, p_socket ps)
106 return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST); 127 return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
107} 128}
108 129
130int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps)
131{
132 return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
133}
134
135int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps)
136{
137 return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
138}
139
140int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps)
141{
142 return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
143}
144
145int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps)
146{
147 return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
148}
149
109int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) 150int opt_set_ip_multicast_loop(lua_State *L, p_socket ps)
110{ 151{
111 return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); 152 return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP);
@@ -116,6 +157,16 @@ int opt_get_ip_multicast_loop(lua_State *L, p_socket ps)
116 return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP); 157 return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP);
117} 158}
118 159
160int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps)
161{
162 return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
163}
164
165int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps)
166{
167 return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
168}
169
119int opt_set_linger(lua_State *L, p_socket ps) 170int opt_set_linger(lua_State *L, p_socket ps)
120{ 171{
121 struct linger li; /* obj, name, table */ 172 struct linger li; /* obj, name, table */
@@ -150,9 +201,7 @@ int opt_get_linger(lua_State *L, p_socket ps)
150 201
151int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) 202int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps)
152{ 203{
153 int val = (int) luaL_checknumber(L, 3); /* obj, name, int */ 204 return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL);
154 return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_TTL,
155 (char *) &val, sizeof(val));
156} 205}
157 206
158int opt_set_ip_multicast_if(lua_State *L, p_socket ps) 207int opt_set_ip_multicast_if(lua_State *L, p_socket ps)
@@ -189,6 +238,21 @@ int opt_set_ip_drop_membersip(lua_State *L, p_socket ps)
189 return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP); 238 return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP);
190} 239}
191 240
241int opt_set_ip6_add_membership(lua_State *L, p_socket ps)
242{
243 return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP);
244}
245
246int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps)
247{
248 return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP);
249}
250
251int opt_get_ip6_v6only(lua_State *L, p_socket ps)
252{
253 return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY);
254}
255
192int opt_set_ip6_v6only(lua_State *L, p_socket ps) 256int opt_set_ip6_v6only(lua_State *L, p_socket ps)
193{ 257{
194 return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); 258 return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY);
@@ -218,6 +282,37 @@ static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
218 return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); 282 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
219} 283}
220 284
285static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
286{
287 struct ipv6_mreq val; /* obj, opt-name, table */
288 memset(&val, 0, sizeof(val));
289 if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
290 lua_pushstring(L, "multiaddr");
291 lua_gettable(L, 3);
292 if (!lua_isstring(L, -1))
293 luaL_argerror(L, 3, "string 'multiaddr' field expected");
294 if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr))
295 luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
296 lua_pushstring(L, "interface");
297 lua_gettable(L, 3);
298 /* By default we listen to interface on default route
299 * (sigh). However, interface= can override it. We support either
300 * number, or name for it. */
301 if (!lua_isnil(L, -1)) {
302 if (lua_isnumber(L, -1)) {
303 val.ipv6mr_interface = lua_tonumber(L, -1);
304 } else if (lua_isstring(L, -1)) {
305 if (!(val.ipv6mr_interface = if_nametoindex(lua_tostring(L, -1)))) {
306 lua_pushnil(L);
307 lua_pushstring(L, "nonexistent interface");
308 return 2;
309 }
310 } else
311 luaL_argerror(L, -1, "number/string 'interface' field expected");
312 }
313 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
314}
315
221static 316static
222int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) 317int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
223{ 318{
@@ -256,15 +351,15 @@ static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
256 351
257int opt_get_error(lua_State *L, p_socket ps) 352int opt_get_error(lua_State *L, p_socket ps)
258{ 353{
259 int val = 0; 354 int val = 0;
260 socklen_t len = sizeof(val); 355 socklen_t len = sizeof(val);
261 if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) { 356 if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) {
262 lua_pushnil(L); 357 lua_pushnil(L);
263 lua_pushstring(L, "getsockopt failed"); 358 lua_pushstring(L, "getsockopt failed");
264 return 2; 359 return 2;
265 } 360 }
266 lua_pushstring(L, socket_strerror(val)); 361 lua_pushstring(L, socket_strerror(val));
267 return 1; 362 return 1;
268} 363}
269 364
270static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) 365static int opt_setboolean(lua_State *L, p_socket ps, int level, int name)
@@ -273,3 +368,19 @@ static int opt_setboolean(lua_State *L, p_socket ps, int level, int name)
273 return opt_set(L, ps, level, name, (char *) &val, sizeof(val)); 368 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
274} 369}
275 370
371static int opt_getint(lua_State *L, p_socket ps, int level, int name)
372{
373 int val = 0;
374 int len = sizeof(val);
375 int err = opt_get(L, ps, level, name, (char *) &val, &len);
376 if (err)
377 return err;
378 lua_pushnumber(L, val);
379 return 1;
380}
381
382static int opt_setint(lua_State *L, p_socket ps, int level, int name)
383{
384 int val = (int) lua_tonumber(L, 3); /* obj, name, int */
385 return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
386}