diff options
| author | Diego Nehab <diego@impa.br> | 2013-05-30 16:20:34 +0800 |
|---|---|---|
| committer | Diego Nehab <diego@impa.br> | 2013-05-30 16:20:34 +0800 |
| commit | a233e27865d96566a6cb13960d08605ce34d9f0d (patch) | |
| tree | 6ef3219bec0c29bbb14ce92b5c2f4dc46b42dbc6 /src/options.c | |
| parent | 5341131cd07bf4f66ce242980b5f3cfbbf45ea12 (diff) | |
| download | luasocket-a233e27865d96566a6cb13960d08605ce34d9f0d.tar.gz luasocket-a233e27865d96566a6cb13960d08605ce34d9f0d.tar.bz2 luasocket-a233e27865d96566a6cb13960d08605ce34d9f0d.zip | |
Leaving if in src/ but out of build for now.
Diffstat (limited to 'src/options.c')
| -rw-r--r-- | src/options.c | 135 |
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 | \*=========================================================================*/ |
| 16 | static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); | 34 | static int opt_setmembership(lua_State *L, p_socket ps, int level, int name); |
| 35 | static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name); | ||
| 17 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); | 36 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name); |
| 18 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); | 37 | static int opt_getboolean(lua_State *L, p_socket ps, int level, int name); |
| 38 | static int opt_setint(lua_State *L, p_socket ps, int level, int name); | ||
| 39 | static int opt_getint(lua_State *L, p_socket ps, int level, int name); | ||
| 19 | static int opt_set(lua_State *L, p_socket ps, int level, int name, | 40 | static int opt_set(lua_State *L, p_socket ps, int level, int name, |
| 20 | void *val, int len); | 41 | void *val, int len); |
| 21 | static int opt_get(lua_State *L, p_socket ps, int level, int name, | 42 | static 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 | ||
| 130 | int 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 | |||
| 135 | int 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 | |||
| 140 | int 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 | |||
| 145 | int 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 | |||
| 109 | int opt_set_ip_multicast_loop(lua_State *L, p_socket ps) | 150 | int 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 | ||
| 160 | int 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 | |||
| 165 | int 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 | |||
| 119 | int opt_set_linger(lua_State *L, p_socket ps) | 170 | int 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 | ||
| 151 | int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps) | 202 | int 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 | ||
| 158 | int opt_set_ip_multicast_if(lua_State *L, p_socket ps) | 207 | int 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 | ||
| 241 | int 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 | |||
| 246 | int 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 | |||
| 251 | int opt_get_ip6_v6only(lua_State *L, p_socket ps) | ||
| 252 | { | ||
| 253 | return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY); | ||
| 254 | } | ||
| 255 | |||
| 192 | int opt_set_ip6_v6only(lua_State *L, p_socket ps) | 256 | int 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 | ||
| 285 | static 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 | |||
| 221 | static | 316 | static |
| 222 | int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len) | 317 | int 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 | ||
| 257 | int opt_get_error(lua_State *L, p_socket ps) | 352 | int 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 | ||
| 270 | static int opt_setboolean(lua_State *L, p_socket ps, int level, int name) | 365 | static 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 | ||
| 371 | static 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 | |||
| 382 | static 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 | } | ||
