You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua_ip.c 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "lua_common.h"
  17. #include "libserver/maps/map_helpers.h"
  18. /***
  19. * @module rspamd_ip
  20. * `rspamd_ip` is a helper module to simplify IP addresses manipulations.
  21. * @example
  22. local print_octets = function(ip)
  23. print('Normal order octets:')
  24. for _,o in ipairs(ip:str_octets()) do
  25. print(o)
  26. end
  27. print('Reversed order octets:')
  28. for _,o in ipairs(ip:inversed_str_octets()) do
  29. print(o)
  30. end
  31. print('Numeric octets:')
  32. for _,o in ipairs(ip:to_table()) do
  33. print(o)
  34. end
  35. end
  36. local rspamd_ip = require "rspamd_ip"
  37. -- Create ipv4
  38. local ip4 = rspamd_ip.from_string('127.0.0.1')
  39. -- Implicit conversion to string
  40. print(ip4)
  41. -- Numeric version
  42. print(ip4:get_version())
  43. print_octets(ip4)
  44. -- Create a sample ipv6 address
  45. local ip6 = rspamd_ip.from_string('2001:41d0:8:dd9a::100')
  46. print(ip6)
  47. print(ip6:get_version())
  48. print_octets(ip6)
  49. */
  50. /***
  51. * @method ip:to_string([pretty=false])
  52. * Converts valid IP address to string
  53. * @param {bool} pretty print IP address with port and braces (for IPv6)
  54. * @return {string or nil} string representation of IP or `nil` if IP is invalid
  55. */
  56. LUA_FUNCTION_DEF (ip, to_string);
  57. /***
  58. * @method ip:to_number()
  59. * Converts valid IP address to number or list of numbers in case of IPv6
  60. * @return {integer(s) or nil} numeric representation of IP in *host* byte order or `nil` if IP is invalid
  61. */
  62. LUA_FUNCTION_DEF (ip, to_number);
  63. /***
  64. * @method ip:to_table()
  65. * Converts valid IP address to the table of numeric octets
  66. * @return {table or nil} numeric octets of IP address or `nil` if IP is invalid
  67. * @example
  68. local ip = rspamd_ip.from_string('127.0.0.1')
  69. for _,o in ipairs(ip:to_table()) do
  70. print(o)
  71. end
  72. -- Output:
  73. -- 127
  74. -- 0
  75. -- 0
  76. -- 1
  77. */
  78. LUA_FUNCTION_DEF (ip, to_table);
  79. /***
  80. * @method ip:str_octets()
  81. * Converts valid IP address to the table of string octets. The difference from
  82. * @see ip:to_table() is that this method returns just hex strings for ipv6
  83. * addresses.
  84. * @return {table or nil} string octets of IP address or `nil` if IP is invalid
  85. */
  86. LUA_FUNCTION_DEF (ip, str_octets);
  87. /***
  88. * @method ip:str_octets()
  89. * Converts valid IP address to the table of string octets in reversed order. The difference from
  90. * @see ip:to_table() is that this method returns just hex strings for ipv6
  91. * addresses.
  92. * @return {table or nil} string octets of IP address or `nil` if IP is invalid
  93. * @example
  94. local ip = rspamd_ip.from_string('127.0.0.1')
  95. for _,o in ipairs(ip:to_table()) do
  96. print(o)
  97. end
  98. -- Output:
  99. -- 1
  100. -- 0
  101. -- 0
  102. -- 127
  103. */
  104. LUA_FUNCTION_DEF (ip, inversed_str_octets);
  105. /***
  106. * @function rspamd_ip.from_string(line)
  107. * Create IP address from its string representation.
  108. * @param {string} line valid IP address string (either ipv4 or ipv6)
  109. * @return {ip} new ip object or `nil` if input is invalid
  110. */
  111. LUA_FUNCTION_DEF (ip, from_string);
  112. /***
  113. * @method ip:__gc()
  114. * Automatically destroys IP object.
  115. */
  116. LUA_FUNCTION_DEF (ip, destroy);
  117. /***
  118. * @method ip:get_version()
  119. * Gets numeric version of ip address
  120. * @return {number} `4` for IPv4 and `6` for IPv6
  121. */
  122. LUA_FUNCTION_DEF (ip, get_version);
  123. /***
  124. * @method ip:is_valid()
  125. * Checks if an IP object is a valid IP address.
  126. * @return {boolean} `true` if IP is valid and `false` otherwise
  127. */
  128. LUA_FUNCTION_DEF (ip, is_valid);
  129. /***
  130. * @method ip:apply_mask(mask)
  131. * Applies mask to IP address, resetting up to `mask` least significant bits to zero.
  132. * @param {integer} mask how many bits to reset
  133. * @return {ip} new IP object with `mask` bits reset
  134. */
  135. LUA_FUNCTION_DEF (ip, apply_mask);
  136. /***
  137. * @method ip:__eq(other)
  138. * Compares two IP addresses
  139. * @param {ip} other IP to compare
  140. * @return {boolean} `true` if two objects are the same
  141. */
  142. LUA_FUNCTION_DEF (ip, equal);
  143. /***
  144. * @method ip:copy()
  145. * Performs deep copy of IP address.
  146. * @return {ip} a fresh copy of IP address
  147. */
  148. LUA_FUNCTION_DEF (ip, copy);
  149. /**
  150. * @method ip:get_port()
  151. * Returns associated port for this IP address
  152. * @return {number} port number or nil
  153. */
  154. LUA_FUNCTION_DEF (ip, get_port);
  155. /***
  156. * @method ip:is_local()
  157. * Returns true if address is local one
  158. * @return {boolean} `true` if address is local
  159. */
  160. LUA_FUNCTION_DEF (ip, is_local);
  161. /***
  162. * @method ip:less_than(other)
  163. * Returns true if address is less than other
  164. * @return {boolean}
  165. */
  166. LUA_FUNCTION_DEF (ip, less_than);
  167. static const struct luaL_reg iplib_m[] = {
  168. LUA_INTERFACE_DEF (ip, to_string),
  169. LUA_INTERFACE_DEF (ip, to_table),
  170. LUA_INTERFACE_DEF (ip, to_number),
  171. LUA_INTERFACE_DEF (ip, str_octets),
  172. LUA_INTERFACE_DEF (ip, inversed_str_octets),
  173. LUA_INTERFACE_DEF (ip, get_version),
  174. LUA_INTERFACE_DEF (ip, get_port),
  175. LUA_INTERFACE_DEF (ip, is_valid),
  176. LUA_INTERFACE_DEF (ip, apply_mask),
  177. LUA_INTERFACE_DEF (ip, copy),
  178. LUA_INTERFACE_DEF (ip, is_local),
  179. {"tostring", lua_ip_to_string},
  180. {"totable", lua_ip_to_table},
  181. {"tonumber", lua_ip_to_number},
  182. {"__tostring", lua_ip_to_string},
  183. {"__eq", lua_ip_equal},
  184. {"__gc", lua_ip_destroy},
  185. {"__lt", lua_ip_less_than},
  186. {NULL, NULL}
  187. };
  188. static const struct luaL_reg iplib_f[] = {
  189. LUA_INTERFACE_DEF (ip, from_string),
  190. {"fromstring", lua_ip_from_string},
  191. {"fromip", lua_ip_copy},
  192. {"from_ip", lua_ip_copy},
  193. {NULL, NULL}
  194. };
  195. static struct rspamd_lua_ip *
  196. lua_ip_new (lua_State *L, struct rspamd_lua_ip *old)
  197. {
  198. struct rspamd_lua_ip *ip, **pip;
  199. ip = g_malloc0 (sizeof (*ip));
  200. if (old != NULL && old->addr != NULL) {
  201. ip->addr = rspamd_inet_address_copy (old->addr);
  202. }
  203. pip = lua_newuserdata (L, sizeof (struct rspamd_lua_ip *));
  204. rspamd_lua_setclass (L, "rspamd{ip}", -1);
  205. *pip = ip;
  206. return ip;
  207. }
  208. struct rspamd_lua_ip *
  209. lua_check_ip (lua_State * L, gint pos)
  210. {
  211. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{ip}");
  212. luaL_argcheck (L, ud != NULL, pos, "'ip' expected");
  213. return ud ? *((struct rspamd_lua_ip **)ud) : NULL;
  214. }
  215. static gint
  216. lua_ip_to_table (lua_State *L)
  217. {
  218. LUA_TRACE_POINT;
  219. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  220. guint max, i;
  221. guint8 *ptr;
  222. if (ip != NULL && ip->addr) {
  223. ptr = rspamd_inet_address_get_hash_key (ip->addr, &max);
  224. lua_createtable (L, max, 0);
  225. for (i = 1; i <= max; i++, ptr++) {
  226. lua_pushinteger (L, *ptr);
  227. lua_rawseti (L, -2, i);
  228. }
  229. }
  230. else {
  231. lua_pushnil (L);
  232. }
  233. return 1;
  234. }
  235. static gint
  236. lua_ip_str_octets (lua_State *L)
  237. {
  238. LUA_TRACE_POINT;
  239. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  240. guint max, i;
  241. guint8 *ptr;
  242. gint af;
  243. char numbuf[8];
  244. if (ip != NULL && ip->addr) {
  245. af = rspamd_inet_address_get_af (ip->addr);
  246. ptr = rspamd_inet_address_get_hash_key (ip->addr, &max);
  247. lua_createtable (L, max * 2, 0);
  248. for (i = 1; i <= max; i++, ptr++) {
  249. if (af == AF_INET) {
  250. rspamd_snprintf (numbuf, sizeof (numbuf), "%d", *ptr);
  251. lua_pushstring (L, numbuf);
  252. lua_rawseti (L, -2, i);
  253. }
  254. else {
  255. rspamd_snprintf (numbuf,
  256. sizeof (numbuf),
  257. "%xd",
  258. (*ptr & 0xf0) >> 4);
  259. lua_pushstring (L, numbuf);
  260. lua_rawseti (L, -2, i * 2 - 1);
  261. rspamd_snprintf (numbuf, sizeof (numbuf), "%xd", *ptr & 0x0f);
  262. lua_pushstring (L, numbuf);
  263. lua_rawseti (L, -2, i * 2);
  264. }
  265. }
  266. }
  267. else {
  268. lua_pushnil (L);
  269. }
  270. return 1;
  271. }
  272. static gint
  273. lua_ip_inversed_str_octets (lua_State *L)
  274. {
  275. LUA_TRACE_POINT;
  276. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  277. guint max, i;
  278. guint8 *ptr;
  279. char numbuf[4];
  280. gint af;
  281. if (ip != NULL && ip->addr) {
  282. ptr = rspamd_inet_address_get_hash_key (ip->addr, &max);
  283. af = rspamd_inet_address_get_af (ip->addr);
  284. lua_createtable (L, max * 2, 0);
  285. ptr += max - 1;
  286. for (i = 1; i <= max; i++, ptr--) {
  287. if (af == AF_INET) {
  288. rspamd_snprintf (numbuf, sizeof (numbuf), "%d", *ptr);
  289. lua_pushstring (L, numbuf);
  290. lua_rawseti (L, -2, i);
  291. }
  292. else {
  293. rspamd_snprintf (numbuf, sizeof (numbuf), "%xd", *ptr & 0x0f);
  294. lua_pushstring (L, numbuf);
  295. lua_rawseti (L, -2, i * 2 - 1);
  296. rspamd_snprintf (numbuf,
  297. sizeof (numbuf),
  298. "%xd",
  299. (*ptr & 0xf0) >> 4);
  300. lua_pushstring (L, numbuf);
  301. lua_rawseti (L, -2, i * 2);
  302. }
  303. }
  304. }
  305. else {
  306. lua_pushnil (L);
  307. }
  308. return 1;
  309. }
  310. static gint
  311. lua_ip_to_string (lua_State *L)
  312. {
  313. LUA_TRACE_POINT;
  314. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  315. if (ip != NULL && ip->addr) {
  316. if (lua_isboolean (L, 2) && lua_toboolean (L, 2) == true) {
  317. lua_pushstring (L, rspamd_inet_address_to_string_pretty (ip->addr));
  318. }
  319. else {
  320. lua_pushstring (L, rspamd_inet_address_to_string (ip->addr));
  321. }
  322. }
  323. else {
  324. luaL_error (L, "invalid arguments");
  325. }
  326. return 1;
  327. }
  328. static gint
  329. lua_ip_get_port (lua_State *L)
  330. {
  331. LUA_TRACE_POINT;
  332. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  333. if (ip != NULL && ip->addr) {
  334. lua_pushinteger (L, rspamd_inet_address_get_port (ip->addr));
  335. }
  336. else {
  337. lua_pushnil (L);
  338. }
  339. return 1;
  340. }
  341. static gint
  342. lua_ip_from_string (lua_State *L)
  343. {
  344. LUA_TRACE_POINT;
  345. struct rspamd_lua_ip *ip;
  346. const gchar *ip_str;
  347. gsize len;
  348. ip_str = luaL_checklstring (L, 1, &len);
  349. if (ip_str) {
  350. ip = lua_ip_new (L, NULL);
  351. if (!rspamd_parse_inet_address (&ip->addr,
  352. ip_str, len, RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) {
  353. msg_warn ("cannot parse ip: %*s", (gint) len, ip_str);
  354. ip->addr = NULL;
  355. }
  356. }
  357. else {
  358. lua_pushnil (L);
  359. }
  360. return 1;
  361. }
  362. static gint
  363. lua_ip_to_number (lua_State *L)
  364. {
  365. LUA_TRACE_POINT;
  366. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  367. guint32 c;
  368. guint max, i;
  369. guchar *ptr;
  370. if (ip != NULL && ip->addr) {
  371. ptr = rspamd_inet_address_get_hash_key (ip->addr, &max);
  372. for (i = 0; i < max / sizeof (c); i ++) {
  373. memcpy (&c, ptr + i * sizeof (c), sizeof (c));
  374. lua_pushinteger (L, ntohl (c));
  375. }
  376. return max / sizeof (c);
  377. }
  378. else {
  379. lua_pushnil (L);
  380. }
  381. return 1;
  382. }
  383. static gint
  384. lua_ip_destroy (lua_State *L)
  385. {
  386. LUA_TRACE_POINT;
  387. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  388. if (ip) {
  389. if (ip->addr) {
  390. rspamd_inet_address_free (ip->addr);
  391. }
  392. g_free (ip);
  393. }
  394. return 0;
  395. }
  396. static gint
  397. lua_ip_get_version (lua_State *L)
  398. {
  399. LUA_TRACE_POINT;
  400. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  401. if (ip && ip->addr) {
  402. lua_pushinteger (L, rspamd_inet_address_get_af (ip->addr) == AF_INET6 ?
  403. 6 : 4);
  404. }
  405. else {
  406. lua_pushnil (L);
  407. }
  408. return 1;
  409. }
  410. static gint
  411. lua_ip_is_valid (lua_State *L)
  412. {
  413. LUA_TRACE_POINT;
  414. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  415. if (ip) {
  416. lua_pushboolean (L, ip->addr != NULL);
  417. }
  418. else {
  419. lua_pushnil (L);
  420. }
  421. return 1;
  422. }
  423. static gint
  424. lua_ip_apply_mask (lua_State *L)
  425. {
  426. LUA_TRACE_POINT;
  427. struct rspamd_lua_ip *ip = lua_check_ip (L, 1), *nip;
  428. gint mask;
  429. mask = lua_tonumber (L, 2);
  430. if (mask > 0 && ip != NULL && ip->addr) {
  431. nip = lua_ip_new (L, ip);
  432. rspamd_inet_address_apply_mask (nip->addr, mask);
  433. }
  434. else {
  435. lua_pushnil (L);
  436. }
  437. return 1;
  438. }
  439. static gint
  440. lua_ip_equal (lua_State *L)
  441. {
  442. LUA_TRACE_POINT;
  443. struct rspamd_lua_ip *ip1 = lua_check_ip (L, 1),
  444. *ip2 = lua_check_ip (L, 2);
  445. gboolean res = FALSE;
  446. if (ip1 && ip2 && ip1->addr && ip2->addr) {
  447. res = rspamd_inet_address_compare (ip1->addr, ip2->addr, TRUE) == 0;
  448. }
  449. lua_pushboolean (L, res);
  450. return 1;
  451. }
  452. static gint
  453. lua_ip_copy (lua_State *L)
  454. {
  455. LUA_TRACE_POINT;
  456. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  457. if (ip) {
  458. lua_ip_new (L, ip);
  459. }
  460. else {
  461. lua_pushnil (L);
  462. }
  463. return 1;
  464. }
  465. static gint
  466. lua_ip_is_local (lua_State *L)
  467. {
  468. struct rspamd_lua_ip *ip = lua_check_ip (L, 1);
  469. gboolean check_laddrs = TRUE;
  470. if (ip && ip->addr) {
  471. if (lua_type (L, 2) == LUA_TBOOLEAN) {
  472. check_laddrs = lua_toboolean (L, 2);
  473. }
  474. if ( rspamd_inet_address_is_local (ip->addr)) {
  475. lua_pushboolean (L, true);
  476. return 1;
  477. }
  478. else if (check_laddrs) {
  479. struct rspamd_radix_map_helper *local_addrs =
  480. rspamd_inet_library_get_lib_ctx ();
  481. if (local_addrs) {
  482. if (rspamd_match_radix_map_addr (local_addrs, ip->addr) != NULL) {
  483. lua_pushboolean (L, true);
  484. return 1;
  485. }
  486. }
  487. }
  488. lua_pushboolean (L, false);
  489. }
  490. else {
  491. lua_pushnil (L);
  492. }
  493. return 1;
  494. }
  495. static gint
  496. lua_ip_less_than (lua_State *L)
  497. {
  498. LUA_TRACE_POINT;
  499. struct rspamd_lua_ip *ip = lua_check_ip (L, 1),
  500. *other = lua_check_ip (L, 2);
  501. if (ip && other) {
  502. lua_pushboolean (L,
  503. rspamd_inet_address_compare (ip->addr, other->addr, true) < 0);
  504. }
  505. else {
  506. lua_pushnil (L);
  507. }
  508. return 1;
  509. }
  510. void
  511. rspamd_lua_ip_push (lua_State *L, rspamd_inet_addr_t *addr)
  512. {
  513. struct rspamd_lua_ip *ip, **pip;
  514. ip = g_malloc0 (sizeof (struct rspamd_lua_ip));
  515. ip->addr = rspamd_inet_address_copy (addr);
  516. pip = lua_newuserdata (L, sizeof (struct rspamd_lua_ip *));
  517. rspamd_lua_setclass (L, "rspamd{ip}", -1);
  518. *pip = ip;
  519. }
  520. void
  521. rspamd_lua_ip_push_fromstring (lua_State *L, const gchar *ip_str)
  522. {
  523. struct rspamd_lua_ip *ip, **pip;
  524. if (ip_str == NULL) {
  525. lua_pushnil (L);
  526. }
  527. else {
  528. ip = g_malloc0 (sizeof (struct rspamd_lua_ip));
  529. if (rspamd_parse_inet_address (&ip->addr,
  530. ip_str, strlen (ip_str), RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) {
  531. pip = lua_newuserdata (L, sizeof (struct rspamd_lua_ip *));
  532. rspamd_lua_setclass (L, "rspamd{ip}", -1);
  533. *pip = ip;
  534. }
  535. else {
  536. g_free (ip);
  537. lua_pushnil (L);
  538. }
  539. }
  540. }
  541. static gint
  542. lua_load_ip (lua_State * L)
  543. {
  544. lua_newtable (L);
  545. luaL_register (L, NULL, iplib_f);
  546. return 1;
  547. }
  548. void
  549. luaopen_ip (lua_State * L)
  550. {
  551. rspamd_lua_new_class (L, "rspamd{ip}", iplib_m);
  552. lua_pop (L, 1);
  553. rspamd_lua_add_preload (L, "rspamd_ip", lua_load_ip);
  554. }