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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  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. * @example
  86. local ip = rspamd_ip.from_string('fe80::11')
  87. print(table.concat(ip:str_octets(), "."))
  88. -- Output:
  89. -- f.e.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.1
  90. */
  91. LUA_FUNCTION_DEF(ip, str_octets);
  92. /***
  93. * @method ip:inversed_str_octets()
  94. * Converts valid IP address to the table of string octets in reversed order. The difference from
  95. * @see ip:to_table() is that this method returns just hex strings for ipv6
  96. * addresses in reversed order.
  97. * @return {table or nil} string octets of IP address or `nil` if IP is invalid
  98. * @example
  99. local ip = rspamd_ip.from_string('fe80::11')
  100. print(table.concat(ip:inversed_str_octets(), "."))
  101. -- Output:
  102. -- 1.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f
  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. static const struct luaL_reg iplib_f[] = {
  188. LUA_INTERFACE_DEF(ip, from_string),
  189. {"fromstring", lua_ip_from_string},
  190. {"fromip", lua_ip_copy},
  191. {"from_ip", lua_ip_copy},
  192. {NULL, NULL}};
  193. static struct rspamd_lua_ip *
  194. lua_ip_new(lua_State *L, struct rspamd_lua_ip *old)
  195. {
  196. struct rspamd_lua_ip *ip, **pip;
  197. ip = g_malloc0(sizeof(*ip));
  198. if (old != NULL && old->addr != NULL) {
  199. ip->addr = rspamd_inet_address_copy(old->addr, NULL);
  200. }
  201. pip = lua_newuserdata(L, sizeof(struct rspamd_lua_ip *));
  202. rspamd_lua_setclass(L, rspamd_ip_classname, -1);
  203. *pip = ip;
  204. return ip;
  205. }
  206. struct rspamd_lua_ip *
  207. lua_check_ip(lua_State *L, gint pos)
  208. {
  209. void *ud = rspamd_lua_check_udata(L, pos, rspamd_ip_classname);
  210. luaL_argcheck(L, ud != NULL, pos, "'ip' expected");
  211. return ud ? *((struct rspamd_lua_ip **) ud) : NULL;
  212. }
  213. static gint
  214. lua_ip_to_table(lua_State *L)
  215. {
  216. LUA_TRACE_POINT;
  217. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  218. guint max, i;
  219. guint8 *ptr;
  220. if (ip != NULL && ip->addr) {
  221. ptr = rspamd_inet_address_get_hash_key(ip->addr, &max);
  222. lua_createtable(L, max, 0);
  223. for (i = 1; i <= max; i++, ptr++) {
  224. lua_pushinteger(L, *ptr);
  225. lua_rawseti(L, -2, i);
  226. }
  227. }
  228. else {
  229. lua_pushnil(L);
  230. }
  231. return 1;
  232. }
  233. static gint
  234. lua_ip_str_octets(lua_State *L)
  235. {
  236. LUA_TRACE_POINT;
  237. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  238. guint max, i;
  239. guint8 *ptr;
  240. gint af;
  241. char numbuf[8];
  242. if (ip != NULL && ip->addr) {
  243. af = rspamd_inet_address_get_af(ip->addr);
  244. ptr = rspamd_inet_address_get_hash_key(ip->addr, &max);
  245. lua_createtable(L, max * 2, 0);
  246. for (i = 1; i <= max; i++, ptr++) {
  247. if (af == AF_INET) {
  248. rspamd_snprintf(numbuf, sizeof(numbuf), "%d", *ptr);
  249. lua_pushstring(L, numbuf);
  250. lua_rawseti(L, -2, i);
  251. }
  252. else {
  253. rspamd_snprintf(numbuf,
  254. sizeof(numbuf),
  255. "%xd",
  256. (*ptr & 0xf0) >> 4);
  257. lua_pushstring(L, numbuf);
  258. lua_rawseti(L, -2, i * 2 - 1);
  259. rspamd_snprintf(numbuf, sizeof(numbuf), "%xd", *ptr & 0x0f);
  260. lua_pushstring(L, numbuf);
  261. lua_rawseti(L, -2, i * 2);
  262. }
  263. }
  264. }
  265. else {
  266. lua_pushnil(L);
  267. }
  268. return 1;
  269. }
  270. static gint
  271. lua_ip_inversed_str_octets(lua_State *L)
  272. {
  273. LUA_TRACE_POINT;
  274. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  275. guint max, i;
  276. guint8 *ptr;
  277. char numbuf[4];
  278. gint af;
  279. if (ip != NULL && ip->addr) {
  280. ptr = rspamd_inet_address_get_hash_key(ip->addr, &max);
  281. af = rspamd_inet_address_get_af(ip->addr);
  282. lua_createtable(L, max * 2, 0);
  283. ptr += max - 1;
  284. for (i = 1; i <= max; i++, ptr--) {
  285. if (af == AF_INET) {
  286. rspamd_snprintf(numbuf, sizeof(numbuf), "%d", *ptr);
  287. lua_pushstring(L, numbuf);
  288. lua_rawseti(L, -2, i);
  289. }
  290. else {
  291. rspamd_snprintf(numbuf, sizeof(numbuf), "%xd", *ptr & 0x0f);
  292. lua_pushstring(L, numbuf);
  293. lua_rawseti(L, -2, i * 2 - 1);
  294. rspamd_snprintf(numbuf,
  295. sizeof(numbuf),
  296. "%xd",
  297. (*ptr & 0xf0) >> 4);
  298. lua_pushstring(L, numbuf);
  299. lua_rawseti(L, -2, i * 2);
  300. }
  301. }
  302. }
  303. else {
  304. lua_pushnil(L);
  305. }
  306. return 1;
  307. }
  308. static gint
  309. lua_ip_to_string(lua_State *L)
  310. {
  311. LUA_TRACE_POINT;
  312. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  313. if (ip != NULL && ip->addr) {
  314. if (lua_isboolean(L, 2) && lua_toboolean(L, 2) == true) {
  315. lua_pushstring(L, rspamd_inet_address_to_string_pretty(ip->addr));
  316. }
  317. else {
  318. lua_pushstring(L, rspamd_inet_address_to_string(ip->addr));
  319. }
  320. }
  321. else {
  322. luaL_error(L, "invalid arguments");
  323. }
  324. return 1;
  325. }
  326. static gint
  327. lua_ip_get_port(lua_State *L)
  328. {
  329. LUA_TRACE_POINT;
  330. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  331. if (ip != NULL && ip->addr) {
  332. lua_pushinteger(L, rspamd_inet_address_get_port(ip->addr));
  333. }
  334. else {
  335. lua_pushnil(L);
  336. }
  337. return 1;
  338. }
  339. static gint
  340. lua_ip_from_string(lua_State *L)
  341. {
  342. LUA_TRACE_POINT;
  343. struct rspamd_lua_ip *ip;
  344. const gchar *ip_str;
  345. gsize len;
  346. ip_str = luaL_checklstring(L, 1, &len);
  347. if (ip_str) {
  348. ip = lua_ip_new(L, NULL);
  349. if (!rspamd_parse_inet_address(&ip->addr,
  350. ip_str, len, RSPAMD_INET_ADDRESS_PARSE_DEFAULT)) {
  351. msg_warn("cannot parse ip: %*s", (gint) len, ip_str);
  352. ip->addr = NULL;
  353. }
  354. }
  355. else {
  356. lua_pushnil(L);
  357. }
  358. return 1;
  359. }
  360. static gint
  361. lua_ip_to_number(lua_State *L)
  362. {
  363. LUA_TRACE_POINT;
  364. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  365. uint32_t c;
  366. guint max, i;
  367. guchar *ptr;
  368. if (ip != NULL && ip->addr) {
  369. ptr = rspamd_inet_address_get_hash_key(ip->addr, &max);
  370. for (i = 0; i < max / sizeof(c); i++) {
  371. memcpy(&c, ptr + i * sizeof(c), sizeof(c));
  372. lua_pushinteger(L, ntohl(c));
  373. }
  374. return max / sizeof(c);
  375. }
  376. else {
  377. lua_pushnil(L);
  378. }
  379. return 1;
  380. }
  381. static gint
  382. lua_ip_destroy(lua_State *L)
  383. {
  384. LUA_TRACE_POINT;
  385. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  386. if (ip) {
  387. if (ip->addr) {
  388. rspamd_inet_address_free(ip->addr);
  389. }
  390. g_free(ip);
  391. }
  392. return 0;
  393. }
  394. static gint
  395. lua_ip_get_version(lua_State *L)
  396. {
  397. LUA_TRACE_POINT;
  398. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  399. if (ip && ip->addr) {
  400. lua_pushinteger(L, rspamd_inet_address_get_af(ip->addr) == AF_INET6 ? 6 : 4);
  401. }
  402. else {
  403. lua_pushnil(L);
  404. }
  405. return 1;
  406. }
  407. static gint
  408. lua_ip_is_valid(lua_State *L)
  409. {
  410. LUA_TRACE_POINT;
  411. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  412. if (ip) {
  413. lua_pushboolean(L, ip->addr != NULL);
  414. }
  415. else {
  416. lua_pushnil(L);
  417. }
  418. return 1;
  419. }
  420. static gint
  421. lua_ip_apply_mask(lua_State *L)
  422. {
  423. LUA_TRACE_POINT;
  424. struct rspamd_lua_ip *ip = lua_check_ip(L, 1), *nip;
  425. gint mask;
  426. mask = lua_tonumber(L, 2);
  427. if (mask > 0 && ip != NULL && ip->addr) {
  428. nip = lua_ip_new(L, ip);
  429. rspamd_inet_address_apply_mask(nip->addr, mask);
  430. }
  431. else {
  432. lua_pushnil(L);
  433. }
  434. return 1;
  435. }
  436. static gint
  437. lua_ip_equal(lua_State *L)
  438. {
  439. LUA_TRACE_POINT;
  440. struct rspamd_lua_ip *ip1 = lua_check_ip(L, 1),
  441. *ip2 = lua_check_ip(L, 2);
  442. gboolean res = FALSE;
  443. if (ip1 && ip2 && ip1->addr && ip2->addr) {
  444. res = rspamd_inet_address_compare(ip1->addr, ip2->addr, TRUE) == 0;
  445. }
  446. lua_pushboolean(L, res);
  447. return 1;
  448. }
  449. static gint
  450. lua_ip_copy(lua_State *L)
  451. {
  452. LUA_TRACE_POINT;
  453. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  454. if (ip) {
  455. lua_ip_new(L, ip);
  456. }
  457. else {
  458. lua_pushnil(L);
  459. }
  460. return 1;
  461. }
  462. static gint
  463. lua_ip_is_local(lua_State *L)
  464. {
  465. struct rspamd_lua_ip *ip = lua_check_ip(L, 1);
  466. gboolean check_laddrs = TRUE;
  467. if (ip && ip->addr) {
  468. if (lua_type(L, 2) == LUA_TBOOLEAN) {
  469. check_laddrs = lua_toboolean(L, 2);
  470. }
  471. if (rspamd_inet_address_is_local(ip->addr)) {
  472. lua_pushboolean(L, true);
  473. return 1;
  474. }
  475. else if (check_laddrs) {
  476. struct rspamd_radix_map_helper *local_addrs =
  477. rspamd_inet_library_get_lib_ctx();
  478. if (local_addrs) {
  479. if (rspamd_match_radix_map_addr(local_addrs, ip->addr) != NULL) {
  480. lua_pushboolean(L, true);
  481. return 1;
  482. }
  483. }
  484. }
  485. lua_pushboolean(L, false);
  486. }
  487. else {
  488. lua_pushnil(L);
  489. }
  490. return 1;
  491. }
  492. static gint
  493. lua_ip_less_than(lua_State *L)
  494. {
  495. LUA_TRACE_POINT;
  496. struct rspamd_lua_ip *ip = lua_check_ip(L, 1),
  497. *other = lua_check_ip(L, 2);
  498. if (ip && other) {
  499. lua_pushboolean(L,
  500. rspamd_inet_address_compare(ip->addr, other->addr, true) < 0);
  501. }
  502. else {
  503. lua_pushnil(L);
  504. }
  505. return 1;
  506. }
  507. void rspamd_lua_ip_push(lua_State *L, rspamd_inet_addr_t *addr)
  508. {
  509. struct rspamd_lua_ip *ip, **pip;
  510. if (addr) {
  511. ip = g_malloc0(sizeof(struct rspamd_lua_ip));
  512. ip->addr = rspamd_inet_address_copy(addr, NULL);
  513. pip = lua_newuserdata(L, sizeof(struct rspamd_lua_ip *));
  514. rspamd_lua_setclass(L, rspamd_ip_classname, -1);
  515. *pip = ip;
  516. }
  517. else {
  518. lua_pushnil(L);
  519. }
  520. }
  521. void 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_classname, -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 luaopen_ip(lua_State *L)
  549. {
  550. rspamd_lua_new_class(L, rspamd_ip_classname, iplib_m);
  551. lua_pop(L, 1);
  552. rspamd_lua_add_preload(L, "rspamd_ip", lua_load_ip);
  553. }