options.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*=========================================================================*\
  2. * Common option interface
  3. * LuaSocket toolkit
  4. \*=========================================================================*/
  5. #include <string.h>
  6. #include "lauxlib.h"
  7. #include "auxiliar.h"
  8. #include "options.h"
  9. #include "inet.h"
  10. /*=========================================================================*\
  11. * Internal functions prototypes
  12. \*=========================================================================*/
  13. static int opt_setmembership(lua_State *L, p_socket ps, int level, int name);
  14. static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name);
  15. static int opt_setboolean(lua_State *L, p_socket ps, int level, int name);
  16. static int opt_getboolean(lua_State *L, p_socket ps, int level, int name);
  17. static int opt_setint(lua_State *L, p_socket ps, int level, int name);
  18. 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,
  20. void *val, int len);
  21. static int opt_get(lua_State *L, p_socket ps, int level, int name,
  22. void *val, int* len);
  23. /*=========================================================================*\
  24. * Exported functions
  25. \*=========================================================================*/
  26. /*-------------------------------------------------------------------------*\
  27. * Calls appropriate option handler
  28. \*-------------------------------------------------------------------------*/
  29. int opt_meth_setoption(lua_State *L, p_opt opt, p_socket ps)
  30. {
  31. const char *name = luaL_checkstring(L, 2); /* obj, name, ... */
  32. while (opt->name && strcmp(name, opt->name))
  33. opt++;
  34. if (!opt->func) {
  35. char msg[57];
  36. sprintf(msg, "unsupported option `%.35s'", name);
  37. luaL_argerror(L, 2, msg);
  38. }
  39. return opt->func(L, ps);
  40. }
  41. int opt_meth_getoption(lua_State *L, p_opt opt, p_socket ps)
  42. {
  43. const char *name = luaL_checkstring(L, 2); /* obj, name, ... */
  44. while (opt->name && strcmp(name, opt->name))
  45. opt++;
  46. if (!opt->func) {
  47. char msg[57];
  48. sprintf(msg, "unsupported option `%.35s'", name);
  49. luaL_argerror(L, 2, msg);
  50. }
  51. return opt->func(L, ps);
  52. }
  53. /* enables reuse of local address */
  54. int opt_set_reuseaddr(lua_State *L, p_socket ps)
  55. {
  56. return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
  57. }
  58. int opt_get_reuseaddr(lua_State *L, p_socket ps)
  59. {
  60. return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEADDR);
  61. }
  62. /* enables reuse of local port */
  63. int opt_set_reuseport(lua_State *L, p_socket ps)
  64. {
  65. return opt_setboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
  66. }
  67. int opt_get_reuseport(lua_State *L, p_socket ps)
  68. {
  69. return opt_getboolean(L, ps, SOL_SOCKET, SO_REUSEPORT);
  70. }
  71. /* disables the Naggle algorithm */
  72. int opt_set_tcp_nodelay(lua_State *L, p_socket ps)
  73. {
  74. return opt_setboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
  75. }
  76. int opt_get_tcp_nodelay(lua_State *L, p_socket ps)
  77. {
  78. return opt_getboolean(L, ps, IPPROTO_TCP, TCP_NODELAY);
  79. }
  80. int opt_set_keepalive(lua_State *L, p_socket ps)
  81. {
  82. return opt_setboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
  83. }
  84. int opt_get_keepalive(lua_State *L, p_socket ps)
  85. {
  86. return opt_getboolean(L, ps, SOL_SOCKET, SO_KEEPALIVE);
  87. }
  88. int opt_set_dontroute(lua_State *L, p_socket ps)
  89. {
  90. return opt_setboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
  91. }
  92. int opt_get_dontroute(lua_State *L, p_socket ps)
  93. {
  94. return opt_getboolean(L, ps, SOL_SOCKET, SO_DONTROUTE);
  95. }
  96. int opt_set_broadcast(lua_State *L, p_socket ps)
  97. {
  98. return opt_setboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
  99. }
  100. int opt_get_broadcast(lua_State *L, p_socket ps)
  101. {
  102. return opt_getboolean(L, ps, SOL_SOCKET, SO_BROADCAST);
  103. }
  104. int opt_set_ip6_unicast_hops(lua_State *L, p_socket ps)
  105. {
  106. return opt_setint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
  107. }
  108. int opt_get_ip6_unicast_hops(lua_State *L, p_socket ps)
  109. {
  110. return opt_getint(L, ps, IPPROTO_IPV6, IPV6_UNICAST_HOPS);
  111. }
  112. int opt_set_ip6_multicast_hops(lua_State *L, p_socket ps)
  113. {
  114. return opt_setint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
  115. }
  116. int opt_get_ip6_multicast_hops(lua_State *L, p_socket ps)
  117. {
  118. return opt_getint(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
  119. }
  120. int opt_set_ip_multicast_loop(lua_State *L, p_socket ps)
  121. {
  122. return opt_setboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP);
  123. }
  124. int opt_get_ip_multicast_loop(lua_State *L, p_socket ps)
  125. {
  126. return opt_getboolean(L, ps, IPPROTO_IP, IP_MULTICAST_LOOP);
  127. }
  128. int opt_set_ip6_multicast_loop(lua_State *L, p_socket ps)
  129. {
  130. return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
  131. }
  132. int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps)
  133. {
  134. return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
  135. }
  136. int opt_set_linger(lua_State *L, p_socket ps)
  137. {
  138. struct linger li; /* obj, name, table */
  139. if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
  140. lua_pushstring(L, "on");
  141. lua_gettable(L, 3);
  142. if (!lua_isboolean(L, -1))
  143. luaL_argerror(L, 3, "boolean 'on' field expected");
  144. li.l_onoff = (u_short) lua_toboolean(L, -1);
  145. lua_pushstring(L, "timeout");
  146. lua_gettable(L, 3);
  147. if (!lua_isnumber(L, -1))
  148. luaL_argerror(L, 3, "number 'timeout' field expected");
  149. li.l_linger = (u_short) lua_tonumber(L, -1);
  150. return opt_set(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(li));
  151. }
  152. int opt_get_linger(lua_State *L, p_socket ps)
  153. {
  154. struct linger li; /* obj, name */
  155. int len = sizeof(li);
  156. int err = opt_get(L, ps, SOL_SOCKET, SO_LINGER, (char *) &li, &len);
  157. if (err)
  158. return err;
  159. lua_newtable(L);
  160. lua_pushboolean(L, li.l_onoff);
  161. lua_setfield(L, -2, "on");
  162. lua_pushinteger(L, li.l_linger);
  163. lua_setfield(L, -2, "timeout");
  164. return 1;
  165. }
  166. int opt_set_ip_multicast_ttl(lua_State *L, p_socket ps)
  167. {
  168. return opt_setint(L, ps, IPPROTO_IP, IP_MULTICAST_TTL);
  169. }
  170. int opt_set_ip_multicast_if(lua_State *L, p_socket ps)
  171. {
  172. const char *address = luaL_checkstring(L, 3); /* obj, name, ip */
  173. struct in_addr val;
  174. val.s_addr = htonl(INADDR_ANY);
  175. if (strcmp(address, "*") && !inet_aton(address, &val))
  176. luaL_argerror(L, 3, "ip expected");
  177. return opt_set(L, ps, IPPROTO_IP, IP_MULTICAST_IF,
  178. (char *) &val, sizeof(val));
  179. }
  180. int opt_get_ip_multicast_if(lua_State *L, p_socket ps)
  181. {
  182. struct in_addr val;
  183. socklen_t len = sizeof(val);
  184. if (getsockopt(*ps, IPPROTO_IP, IP_MULTICAST_IF, (char *) &val, &len) < 0) {
  185. lua_pushnil(L);
  186. lua_pushstring(L, "getsockopt failed");
  187. return 2;
  188. }
  189. lua_pushstring(L, inet_ntoa(val));
  190. return 1;
  191. }
  192. int opt_set_ip_add_membership(lua_State *L, p_socket ps)
  193. {
  194. return opt_setmembership(L, ps, IPPROTO_IP, IP_ADD_MEMBERSHIP);
  195. }
  196. int opt_set_ip_drop_membersip(lua_State *L, p_socket ps)
  197. {
  198. return opt_setmembership(L, ps, IPPROTO_IP, IP_DROP_MEMBERSHIP);
  199. }
  200. int opt_set_ip6_add_membership(lua_State *L, p_socket ps)
  201. {
  202. return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP);
  203. }
  204. int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps)
  205. {
  206. return opt_ip6_setmembership(L, ps, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP);
  207. }
  208. int opt_get_ip6_v6only(lua_State *L, p_socket ps)
  209. {
  210. return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY);
  211. }
  212. int opt_set_ip6_v6only(lua_State *L, p_socket ps)
  213. {
  214. return opt_setboolean(L, ps, IPPROTO_IPV6, IPV6_V6ONLY);
  215. }
  216. /*=========================================================================*\
  217. * Auxiliar functions
  218. \*=========================================================================*/
  219. static int opt_setmembership(lua_State *L, p_socket ps, int level, int name)
  220. {
  221. struct ip_mreq val; /* obj, name, table */
  222. if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
  223. lua_pushstring(L, "multiaddr");
  224. lua_gettable(L, 3);
  225. if (!lua_isstring(L, -1))
  226. luaL_argerror(L, 3, "string 'multiaddr' field expected");
  227. if (!inet_aton(lua_tostring(L, -1), &val.imr_multiaddr))
  228. luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
  229. lua_pushstring(L, "interface");
  230. lua_gettable(L, 3);
  231. if (!lua_isstring(L, -1))
  232. luaL_argerror(L, 3, "string 'interface' field expected");
  233. val.imr_interface.s_addr = htonl(INADDR_ANY);
  234. if (strcmp(lua_tostring(L, -1), "*") &&
  235. !inet_aton(lua_tostring(L, -1), &val.imr_interface))
  236. luaL_argerror(L, 3, "invalid 'interface' ip address");
  237. return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
  238. }
  239. static int opt_ip6_setmembership(lua_State *L, p_socket ps, int level, int name)
  240. {
  241. struct ipv6_mreq val; /* obj, opt-name, table */
  242. memset(&val, 0, sizeof(val));
  243. if (!lua_istable(L, 3)) auxiliar_typeerror(L,3,lua_typename(L, LUA_TTABLE));
  244. lua_pushstring(L, "multiaddr");
  245. lua_gettable(L, 3);
  246. if (!lua_isstring(L, -1))
  247. luaL_argerror(L, 3, "string 'multiaddr' field expected");
  248. if (!inet_pton(AF_INET6, lua_tostring(L, -1), &val.ipv6mr_multiaddr))
  249. luaL_argerror(L, 3, "invalid 'multiaddr' ip address");
  250. lua_pushstring(L, "interface");
  251. lua_gettable(L, 3);
  252. /* By default we listen to interface on default route
  253. * (sigh). However, interface= can override it. We should
  254. * support either number, or name for it. Waiting for
  255. * windows port of if_nametoindex */
  256. if (!lua_isnil(L, -1)) {
  257. if (lua_isnumber(L, -1)) {
  258. val.ipv6mr_interface = (unsigned int) lua_tonumber(L, -1);
  259. } else
  260. luaL_argerror(L, -1, "number 'interface' field expected");
  261. }
  262. return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
  263. }
  264. static
  265. int opt_get(lua_State *L, p_socket ps, int level, int name, void *val, int* len)
  266. {
  267. socklen_t socklen = *len;
  268. if (getsockopt(*ps, level, name, (char *) val, &socklen) < 0) {
  269. lua_pushnil(L);
  270. lua_pushstring(L, "getsockopt failed");
  271. return 2;
  272. }
  273. *len = socklen;
  274. return 0;
  275. }
  276. static
  277. int opt_set(lua_State *L, p_socket ps, int level, int name, void *val, int len)
  278. {
  279. if (setsockopt(*ps, level, name, (char *) val, len) < 0) {
  280. lua_pushnil(L);
  281. lua_pushstring(L, "setsockopt failed");
  282. return 2;
  283. }
  284. lua_pushnumber(L, 1);
  285. return 1;
  286. }
  287. static int opt_getboolean(lua_State *L, p_socket ps, int level, int name)
  288. {
  289. int val = 0;
  290. int len = sizeof(val);
  291. int err = opt_get(L, ps, level, name, (char *) &val, &len);
  292. if (err)
  293. return err;
  294. lua_pushboolean(L, val);
  295. return 1;
  296. }
  297. int opt_get_error(lua_State *L, p_socket ps)
  298. {
  299. int val = 0;
  300. socklen_t len = sizeof(val);
  301. if (getsockopt(*ps, SOL_SOCKET, SO_ERROR, (char *) &val, &len) < 0) {
  302. lua_pushnil(L);
  303. lua_pushstring(L, "getsockopt failed");
  304. return 2;
  305. }
  306. lua_pushstring(L, socket_strerror(val));
  307. return 1;
  308. }
  309. static int opt_setboolean(lua_State *L, p_socket ps, int level, int name)
  310. {
  311. int val = auxiliar_checkboolean(L, 3); /* obj, name, bool */
  312. return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
  313. }
  314. static int opt_getint(lua_State *L, p_socket ps, int level, int name)
  315. {
  316. int val = 0;
  317. int len = sizeof(val);
  318. int err = opt_get(L, ps, level, name, (char *) &val, &len);
  319. if (err)
  320. return err;
  321. lua_pushnumber(L, val);
  322. return 1;
  323. }
  324. static int opt_setint(lua_State *L, p_socket ps, int level, int name)
  325. {
  326. int val = (int) lua_tonumber(L, 3); /* obj, name, int */
  327. return opt_set(L, ps, level, name, (char *) &val, sizeof(val));
  328. }