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.

addr.c 37KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768
  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 "config.h"
  17. #include "addr.h"
  18. #include "util.h"
  19. #include "map_helpers.h"
  20. #include "logger.h"
  21. #include "cryptobox.h"
  22. #include "unix-std.h"
  23. /* pwd and grp */
  24. #ifdef HAVE_PWD_H
  25. #include <pwd.h>
  26. #endif
  27. #ifdef HAVE_GRP_H
  28. #include <grp.h>
  29. #endif
  30. static struct rspamd_radix_map_helper *local_addrs;
  31. enum {
  32. RSPAMD_IPV6_UNDEFINED = 0,
  33. RSPAMD_IPV6_SUPPORTED,
  34. RSPAMD_IPV6_UNSUPPORTED
  35. } ipv6_status = RSPAMD_IPV6_UNDEFINED;
  36. /**
  37. * Union that is used for storing sockaddrs
  38. */
  39. union sa_union {
  40. struct sockaddr sa;
  41. struct sockaddr_in s4;
  42. struct sockaddr_in6 s6;
  43. struct sockaddr_un su;
  44. struct sockaddr_storage ss;
  45. };
  46. union sa_inet {
  47. struct sockaddr sa;
  48. struct sockaddr_in s4;
  49. struct sockaddr_in6 s6;
  50. };
  51. struct rspamd_addr_unix {
  52. struct sockaddr_un addr;
  53. gint mode;
  54. uid_t owner;
  55. gid_t group;
  56. };
  57. struct rspamd_addr_inet {
  58. union sa_inet addr;
  59. };
  60. struct rspamd_inet_addr_s {
  61. union {
  62. struct rspamd_addr_inet in;
  63. struct rspamd_addr_unix *un;
  64. } u;
  65. gint af;
  66. socklen_t slen;
  67. };
  68. static void
  69. rspamd_ip_validate_af (rspamd_inet_addr_t *addr)
  70. {
  71. if (addr->af != AF_UNIX) {
  72. if (addr->u.in.addr.sa.sa_family != addr->af) {
  73. addr->u.in.addr.sa.sa_family = addr->af;
  74. }
  75. }
  76. else {
  77. addr->u.un->addr.sun_family = AF_UNIX;
  78. }
  79. if (addr->af == AF_INET) {
  80. addr->slen = sizeof (struct sockaddr_in);
  81. }
  82. else if (addr->af == AF_INET6) {
  83. addr->slen = sizeof (struct sockaddr_in6);
  84. }
  85. else if (addr->af == AF_UNIX) {
  86. #ifdef SUN_LEN
  87. addr->slen = SUN_LEN (&addr->u.un->addr);
  88. #else
  89. addr->slen = sizeof (addr->u.un->addr);
  90. #endif
  91. #if defined(FREEBSD) || defined(__APPLE__)
  92. addr->u.un->addr.sun_len = addr->slen;
  93. #endif
  94. }
  95. }
  96. static rspamd_inet_addr_t *
  97. rspamd_inet_addr_create (gint af)
  98. {
  99. rspamd_inet_addr_t *addr;
  100. addr = g_malloc0 (sizeof (rspamd_inet_addr_t));
  101. addr->af = af;
  102. if (af == AF_UNIX) {
  103. addr->u.un = g_malloc0 (sizeof (*addr->u.un));
  104. addr->slen = sizeof (addr->u.un->addr);
  105. }
  106. else {
  107. rspamd_ip_validate_af (addr);
  108. }
  109. return addr;
  110. }
  111. void
  112. rspamd_inet_address_free (rspamd_inet_addr_t *addr)
  113. {
  114. if (addr) {
  115. if (addr->af == AF_UNIX) {
  116. if (addr->u.un) {
  117. g_free (addr->u.un);
  118. }
  119. }
  120. g_free (addr);
  121. }
  122. }
  123. static void
  124. rspamd_ip_check_ipv6 (void)
  125. {
  126. if (ipv6_status == RSPAMD_IPV6_UNDEFINED) {
  127. gint s, r;
  128. struct sockaddr_in6 sin6;
  129. const struct in6_addr ip6_local = IN6ADDR_LOOPBACK_INIT;
  130. s = socket (AF_INET6, SOCK_STREAM, 0);
  131. if (s == -1) {
  132. ipv6_status = RSPAMD_IPV6_UNSUPPORTED;
  133. }
  134. else {
  135. /*
  136. * Some systems allow ipv6 sockets creating but not binding,
  137. * so here we try to bind to some local address and check, whether it
  138. * is possible
  139. */
  140. memset (&sin6, 0, sizeof (sin6));
  141. sin6.sin6_family = AF_INET6;
  142. sin6.sin6_port = rspamd_random_uint64_fast () % 40000 + 20000;
  143. sin6.sin6_addr = ip6_local;
  144. r = bind (s, (struct sockaddr *)&sin6, sizeof (sin6));
  145. if (r == -1 && errno != EADDRINUSE) {
  146. ipv6_status = RSPAMD_IPV6_UNSUPPORTED;
  147. }
  148. else {
  149. ipv6_status = RSPAMD_IPV6_SUPPORTED;
  150. }
  151. close (s);
  152. }
  153. }
  154. }
  155. gboolean
  156. rspamd_ip_is_valid (const rspamd_inet_addr_t *addr)
  157. {
  158. const struct in_addr ip4_any = { INADDR_ANY }, ip4_none = { INADDR_NONE };
  159. const struct in6_addr ip6_any = IN6ADDR_ANY_INIT;
  160. gboolean ret = FALSE;
  161. if (G_LIKELY (addr->af == AF_INET)) {
  162. if (memcmp (&addr->u.in.addr.s4.sin_addr, &ip4_any,
  163. sizeof (struct in_addr)) != 0 &&
  164. memcmp (&addr->u.in.addr.s4.sin_addr, &ip4_none,
  165. sizeof (struct in_addr)) != 0) {
  166. ret = TRUE;
  167. }
  168. }
  169. else if (G_UNLIKELY (addr->af == AF_INET6)) {
  170. if (memcmp (&addr->u.in.addr.s6.sin6_addr, &ip6_any,
  171. sizeof (struct in6_addr)) != 0) {
  172. ret = TRUE;
  173. }
  174. }
  175. return ret;
  176. }
  177. static void
  178. rspamd_enable_accept_event (gint fd, short what, gpointer d)
  179. {
  180. struct event *events = d;
  181. event_del (&events[1]);
  182. event_add (&events[0], NULL);
  183. }
  184. static void
  185. rspamd_disable_accept_events (gint sock, GList *accept_events)
  186. {
  187. GList *cur;
  188. struct event *events;
  189. const gdouble throttling = 0.5;
  190. struct timeval tv;
  191. struct event_base *ev_base;
  192. double_to_tv (throttling, &tv);
  193. for (cur = accept_events; cur != NULL; cur = g_list_next (cur)) {
  194. events = cur->data;
  195. ev_base = event_get_base (&events[0]);
  196. event_del (&events[0]);
  197. event_set (&events[1], sock, EV_TIMEOUT, rspamd_enable_accept_event,
  198. events);
  199. event_base_set (ev_base, &events[1]);
  200. event_add (&events[1], &tv);
  201. }
  202. }
  203. gint
  204. rspamd_accept_from_socket (gint sock, rspamd_inet_addr_t **target,
  205. GList *accept_events)
  206. {
  207. gint nfd, serrno;
  208. union sa_union su;
  209. socklen_t len = sizeof (su);
  210. rspamd_inet_addr_t *addr = NULL;
  211. if ((nfd = accept (sock, &su.sa, &len)) == -1) {
  212. if (target) {
  213. *target = NULL;
  214. }
  215. if (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK) {
  216. return 0;
  217. }
  218. else if (errno == EMFILE || errno == ENFILE) {
  219. /* Temporary disable accept event */
  220. rspamd_disable_accept_events (sock, accept_events);
  221. return 0;
  222. }
  223. return -1;
  224. }
  225. if (su.sa.sa_family == AF_INET6) {
  226. /* Deal with bloody v4 mapped to v6 addresses */
  227. static const guint8 mask[] = {
  228. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  229. };
  230. const guint8 *p;
  231. if (memcmp ((const guint8 *)&su.s6.sin6_addr, mask, sizeof (mask)) == 0) {
  232. p = (const guint8 *)&su.s6.sin6_addr;
  233. if ((p[10] == 0xff && p[11] == 0xff)) {
  234. addr = rspamd_inet_addr_create (AF_INET);
  235. memcpy (&addr->u.in.addr.s4.sin_addr, &p[12],
  236. sizeof (struct in_addr));
  237. }
  238. else {
  239. /* Something strange but not mapped v4 address */
  240. addr = rspamd_inet_addr_create (AF_INET6);
  241. memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
  242. sizeof (struct in6_addr));
  243. }
  244. }
  245. else {
  246. addr = rspamd_inet_addr_create (AF_INET6);
  247. memcpy (&addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
  248. sizeof (struct in6_addr));
  249. }
  250. }
  251. else {
  252. addr = rspamd_inet_addr_create (su.sa.sa_family);
  253. addr->slen = len;
  254. if (addr->af == AF_UNIX) {
  255. len = sizeof (su);
  256. if (getsockname (sock, &su.sa, &len) != -1) {
  257. memcpy (&addr->u.un->addr, &su.su, MIN (len,
  258. sizeof (struct sockaddr_un)));
  259. }
  260. else {
  261. /* Just copy socket address */
  262. memcpy (&addr->u.un->addr, &su.sa, sizeof (struct sockaddr));
  263. }
  264. }
  265. else {
  266. memcpy (&addr->u.in.addr, &su, MIN (len, sizeof (addr->u.in.addr)));
  267. }
  268. }
  269. if (rspamd_socket_nonblocking (nfd) < 0) {
  270. goto out;
  271. }
  272. /* Set close on exec */
  273. if (fcntl (nfd, F_SETFD, FD_CLOEXEC) == -1) {
  274. msg_warn ("fcntl failed: %d, '%s'", errno, strerror (errno));
  275. goto out;
  276. }
  277. if (target) {
  278. *target = addr;
  279. }
  280. else {
  281. /* Avoid leak */
  282. rspamd_inet_address_free (addr);
  283. }
  284. return (nfd);
  285. out:
  286. serrno = errno;
  287. close (nfd);
  288. errno = serrno;
  289. rspamd_inet_address_free (addr);
  290. return (-1);
  291. }
  292. static gboolean
  293. rspamd_parse_unix_path (rspamd_inet_addr_t **target, const char *src)
  294. {
  295. gchar **tokens, **cur_tok, *p, *pwbuf;
  296. glong pwlen;
  297. struct passwd pw, *ppw;
  298. struct group gr, *pgr;
  299. rspamd_inet_addr_t *addr;
  300. bool has_group = false;
  301. tokens = g_strsplit_set (src, " ,", -1);
  302. addr = rspamd_inet_addr_create (AF_UNIX);
  303. rspamd_strlcpy (addr->u.un->addr.sun_path, tokens[0],
  304. sizeof (addr->u.un->addr.sun_path));
  305. #if defined(FREEBSD) || defined(__APPLE__)
  306. addr->u.un->addr.sun_len = SUN_LEN (&addr->u.un->addr);
  307. #endif
  308. addr->u.un->mode = 00644;
  309. addr->u.un->owner = (uid_t)-1;
  310. addr->u.un->group = (gid_t)-1;
  311. cur_tok = &tokens[1];
  312. #ifdef _SC_GETPW_R_SIZE_MAX
  313. pwlen = sysconf (_SC_GETPW_R_SIZE_MAX);
  314. if (pwlen <= 0) {
  315. pwlen = 8192;
  316. }
  317. #else
  318. pwlen = 8192;
  319. #endif
  320. pwbuf = g_malloc0 (pwlen);
  321. while (*cur_tok) {
  322. if (g_ascii_strncasecmp (*cur_tok, "mode=", sizeof ("mode=") - 1) == 0) {
  323. p = strchr (*cur_tok, '=');
  324. /* XXX: add error check */
  325. addr->u.un->mode = strtoul (p + 1, NULL, 0);
  326. if (addr->u.un->mode == 0) {
  327. msg_err ("bad mode: %s", p + 1);
  328. errno = EINVAL;
  329. goto err;
  330. }
  331. }
  332. else if (g_ascii_strncasecmp (*cur_tok, "owner=",
  333. sizeof ("owner=") - 1) == 0) {
  334. p = strchr (*cur_tok, '=');
  335. if (getpwnam_r (p + 1, &pw, pwbuf, pwlen, &ppw) != 0 || ppw == NULL) {
  336. msg_err ("bad user: %s", p + 1);
  337. if (ppw == NULL) {
  338. errno = ENOENT;
  339. }
  340. goto err;
  341. }
  342. addr->u.un->owner = pw.pw_uid;
  343. if (!has_group) {
  344. addr->u.un->group = pw.pw_gid;
  345. }
  346. }
  347. else if (g_ascii_strncasecmp (*cur_tok, "group=",
  348. sizeof ("group=") - 1) == 0) {
  349. p = strchr (*cur_tok, '=');
  350. if (getgrnam_r (p + 1, &gr, pwbuf, pwlen, &pgr) != 0 || pgr == NULL) {
  351. msg_err ("bad group: %s", p + 1);
  352. if (pgr == NULL) {
  353. errno = ENOENT;
  354. }
  355. goto err;
  356. }
  357. has_group = true;
  358. addr->u.un->group = gr.gr_gid;
  359. }
  360. cur_tok ++;
  361. }
  362. g_free (pwbuf);
  363. g_strfreev (tokens);
  364. if (target) {
  365. rspamd_ip_validate_af (addr);
  366. *target = addr;
  367. }
  368. else {
  369. rspamd_inet_address_free (addr);
  370. }
  371. return TRUE;
  372. err:
  373. g_strfreev (tokens);
  374. g_free (pwbuf);
  375. rspamd_inet_address_free (addr);
  376. return FALSE;
  377. }
  378. gboolean
  379. rspamd_parse_inet_address_ip4 (const guchar *text, gsize len, gpointer target)
  380. {
  381. const guchar *p;
  382. guchar c;
  383. guint32 addr = 0, *addrptr = target;
  384. guint octet = 0, n = 0;
  385. g_assert (text != NULL);
  386. g_assert (target != NULL);
  387. if (len == 0) {
  388. len = strlen (text);
  389. }
  390. for (p = text; p < text + len; p++) {
  391. c = *p;
  392. if (c >= '0' && c <= '9') {
  393. octet = octet * 10 + (c - '0');
  394. if (octet > 255) {
  395. return FALSE;
  396. }
  397. continue;
  398. }
  399. if (c == '.') {
  400. addr = (addr << 8) + octet;
  401. octet = 0;
  402. n++;
  403. continue;
  404. }
  405. return FALSE;
  406. }
  407. if (n == 3) {
  408. addr = (addr << 8) + octet;
  409. *addrptr = ntohl (addr);
  410. return TRUE;
  411. }
  412. return FALSE;
  413. }
  414. gboolean
  415. rspamd_parse_inet_address_ip6 (const guchar *text, gsize len, gpointer target)
  416. {
  417. guchar t, *zero = NULL, *s, *d, *addr = target;
  418. const guchar *p, *digit = NULL, *percent;
  419. gsize len4 = 0;
  420. guint n = 8, nibbles = 0, word = 0;
  421. g_assert (text != NULL);
  422. g_assert (target != NULL);
  423. if (len == 0) {
  424. len = strlen (text);
  425. }
  426. /* Ignore trailing semicolon */
  427. if (text[0] == ':') {
  428. p = text + 1;
  429. len--;
  430. }
  431. else {
  432. p = text;
  433. }
  434. /* Check IPv6 scope */
  435. if ((percent = memchr (p, '%', len)) != NULL && percent > p) {
  436. len = percent - p; /* Ignore scope */
  437. }
  438. for (/* void */; len; len--) {
  439. t = *p++;
  440. if (t == ':') {
  441. if (nibbles) {
  442. digit = p;
  443. len4 = len;
  444. *addr++ = (u_char) (word >> 8);
  445. *addr++ = (u_char) (word & 0xff);
  446. if (--n) {
  447. nibbles = 0;
  448. word = 0;
  449. continue;
  450. }
  451. } else {
  452. if (zero == NULL) {
  453. digit = p;
  454. len4 = len;
  455. zero = addr;
  456. continue;
  457. }
  458. }
  459. return FALSE;
  460. }
  461. if (t == '.' && nibbles) {
  462. if (n < 2 || digit == NULL) {
  463. return FALSE;
  464. }
  465. /* IPv4 encoded in IPv6 */
  466. if (!rspamd_parse_inet_address_ip4 (digit, len4 - 1, &word)) {
  467. return FALSE;
  468. }
  469. word = ntohl (word);
  470. *addr++ = (guchar) ((word >> 24) & 0xff);
  471. *addr++ = (guchar) ((word >> 16) & 0xff);
  472. n--;
  473. break;
  474. }
  475. if (++nibbles > 4) {
  476. /* Too many dots */
  477. return FALSE;
  478. }
  479. /* Restore from hex */
  480. if (t >= '0' && t <= '9') {
  481. word = word * 16 + (t - '0');
  482. continue;
  483. }
  484. t |= 0x20;
  485. if (t >= 'a' && t <= 'f') {
  486. word = word * 16 + (t - 'a') + 10;
  487. continue;
  488. }
  489. return FALSE;
  490. }
  491. if (nibbles == 0 && zero == NULL) {
  492. return FALSE;
  493. }
  494. *addr++ = (guchar) (word >> 8);
  495. *addr++ = (guchar) (word & 0xff);
  496. if (--n) {
  497. if (zero) {
  498. n *= 2;
  499. s = addr - 1;
  500. d = s + n;
  501. while (s >= zero) {
  502. *d-- = *s--;
  503. }
  504. memset (zero, 0, n);
  505. return TRUE;
  506. }
  507. } else {
  508. if (zero == NULL) {
  509. return TRUE;
  510. }
  511. }
  512. return FALSE;
  513. }
  514. /* Checks for ipv6 mapped address */
  515. static rspamd_inet_addr_t *
  516. rspamd_inet_address_v6_maybe_map (const struct sockaddr_in6 *sin6)
  517. {
  518. rspamd_inet_addr_t *addr = NULL;
  519. /* 10 zero bytes or 80 bits */
  520. static const guint8 mask[] = {
  521. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  522. };
  523. const guint8 *p;
  524. if (memcmp ((const guint8 *)&sin6->sin6_addr, mask, sizeof (mask)) == 0) {
  525. p = (const guint8 *)&sin6->sin6_addr;
  526. if ((p[10] == 0xff && p[11] == 0xff)) {
  527. addr = rspamd_inet_addr_create (AF_INET);
  528. memcpy (&addr->u.in.addr.s4.sin_addr, &p[12],
  529. sizeof (struct in_addr));
  530. }
  531. else {
  532. /* Something strange but not mapped v4 address */
  533. addr = rspamd_inet_addr_create (AF_INET6);
  534. memcpy (&addr->u.in.addr.s6.sin6_addr, &sin6->sin6_addr,
  535. sizeof (struct in6_addr));
  536. }
  537. }
  538. else {
  539. addr = rspamd_inet_addr_create (AF_INET6);
  540. memcpy (&addr->u.in.addr.s6.sin6_addr, &sin6->sin6_addr,
  541. sizeof (struct in6_addr));
  542. }
  543. return addr;
  544. }
  545. static void
  546. rspamd_inet_address_v6_maybe_map_static (const struct sockaddr_in6 *sin6,
  547. rspamd_inet_addr_t *addr)
  548. {
  549. /* 10 zero bytes or 80 bits */
  550. static const guint8 mask[] = {
  551. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  552. };
  553. const guint8 *p;
  554. if (memcmp ((const guint8 *)&sin6->sin6_addr, mask, sizeof (mask)) == 0) {
  555. p = (const guint8 *)&sin6->sin6_addr;
  556. if ((p[10] == 0xff && p[11] == 0xff)) {
  557. memcpy (&addr->u.in.addr.s4.sin_addr, &p[12],
  558. sizeof (struct in_addr));
  559. addr->af = AF_INET;
  560. addr->slen = sizeof (addr->u.in.addr.s4);
  561. }
  562. else {
  563. /* Something strange but not mapped v4 address */
  564. memcpy (&addr->u.in.addr.s6.sin6_addr, &sin6->sin6_addr,
  565. sizeof (struct in6_addr));
  566. addr->af = AF_INET6;
  567. addr->slen = sizeof (addr->u.in.addr.s6);
  568. }
  569. }
  570. else {
  571. memcpy (&addr->u.in.addr.s6.sin6_addr, &sin6->sin6_addr,
  572. sizeof (struct in6_addr));
  573. addr->af = AF_INET6;
  574. addr->slen = sizeof (addr->u.in.addr.s6);
  575. }
  576. }
  577. gboolean
  578. rspamd_parse_inet_address (rspamd_inet_addr_t **target,
  579. const char *src,
  580. gsize srclen)
  581. {
  582. gboolean ret = FALSE;
  583. rspamd_inet_addr_t *addr = NULL;
  584. union sa_inet su;
  585. const char *end;
  586. char ipbuf[INET6_ADDRSTRLEN + 1];
  587. guint iplen;
  588. gulong portnum;
  589. g_assert (src != NULL);
  590. g_assert (target != NULL);
  591. if (srclen == 0) {
  592. srclen = strlen (src);
  593. }
  594. rspamd_ip_check_ipv6 ();
  595. if (src[0] == '/' || src[0] == '.') {
  596. return rspamd_parse_unix_path (target, src);
  597. }
  598. if (src[0] == '[') {
  599. /* Ipv6 address in format [::1]:port or just [::1] */
  600. end = memchr (src + 1, ']', srclen - 1);
  601. if (end == NULL) {
  602. return FALSE;
  603. }
  604. iplen = end - src - 1;
  605. if (iplen == 0 || iplen >= sizeof (ipbuf)) {
  606. return FALSE;
  607. }
  608. rspamd_strlcpy (ipbuf, src + 1, iplen + 1);
  609. if (rspamd_parse_inet_address_ip6 (ipbuf, iplen,
  610. &su.s6.sin6_addr)) {
  611. addr = rspamd_inet_address_v6_maybe_map (&su.s6);
  612. ret = TRUE;
  613. }
  614. if (ret && end[1] == ':') {
  615. /* Port part */
  616. rspamd_strtoul (end + 1, srclen - iplen - 3, &portnum);
  617. rspamd_inet_address_set_port (addr, portnum);
  618. }
  619. }
  620. else {
  621. if ((end = memchr (src, ':', srclen)) != NULL) {
  622. /* This is either port number and ipv4 addr or ipv6 addr */
  623. /* Search for another semicolon */
  624. if (memchr (end + 1, ':', srclen - (end - src + 1)) &&
  625. rspamd_parse_inet_address_ip6 (src, srclen, &su.s6.sin6_addr)) {
  626. addr = rspamd_inet_address_v6_maybe_map (&su.s6);
  627. ret = TRUE;
  628. }
  629. else {
  630. /* Not ipv6, so try ip:port */
  631. iplen = end - src;
  632. if (iplen >= sizeof (ipbuf) || iplen <= 1) {
  633. return FALSE;
  634. }
  635. else {
  636. rspamd_strlcpy (ipbuf, src, iplen + 1);
  637. }
  638. if (rspamd_parse_inet_address_ip4 (ipbuf, iplen,
  639. &su.s4.sin_addr)) {
  640. addr = rspamd_inet_addr_create (AF_INET);
  641. memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
  642. sizeof (struct in_addr));
  643. rspamd_strtoul (end + 1, srclen - iplen - 1, &portnum);
  644. rspamd_inet_address_set_port (addr, portnum);
  645. ret = TRUE;
  646. }
  647. }
  648. }
  649. else {
  650. if (rspamd_parse_inet_address_ip4 (src, srclen, &su.s4.sin_addr)) {
  651. addr = rspamd_inet_addr_create (AF_INET);
  652. memcpy (&addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
  653. sizeof (struct in_addr));
  654. ret = TRUE;
  655. }
  656. else if (rspamd_parse_inet_address_ip6 (src, srclen, &su.s6.sin6_addr)) {
  657. addr = rspamd_inet_address_v6_maybe_map (&su.s6);
  658. ret = TRUE;
  659. }
  660. }
  661. }
  662. if (ret && target) {
  663. *target = addr;
  664. }
  665. return ret;
  666. }
  667. gboolean
  668. rspamd_parse_inet_address_ip (const char *src, gsize srclen,
  669. rspamd_inet_addr_t *target)
  670. {
  671. const char *end;
  672. char ipbuf[INET6_ADDRSTRLEN + 1];
  673. guint iplen;
  674. gulong portnum;
  675. gboolean ret = FALSE;
  676. union sa_inet su;
  677. g_assert (target != NULL);
  678. g_assert (src != NULL);
  679. if (src[0] == '[') {
  680. /* Ipv6 address in format [::1]:port or just [::1] */
  681. end = memchr (src + 1, ']', srclen - 1);
  682. if (end == NULL) {
  683. return FALSE;
  684. }
  685. iplen = end - src - 1;
  686. if (iplen == 0 || iplen >= sizeof (ipbuf)) {
  687. return FALSE;
  688. }
  689. rspamd_strlcpy (ipbuf, src + 1, iplen + 1);
  690. if (rspamd_parse_inet_address_ip6 (ipbuf, iplen,
  691. &su.s6.sin6_addr)) {
  692. rspamd_inet_address_v6_maybe_map_static (&su.s6, target);
  693. ret = TRUE;
  694. }
  695. if (ret && end[1] == ':') {
  696. /* Port part */
  697. rspamd_strtoul (end + 1, srclen - iplen - 3, &portnum);
  698. rspamd_inet_address_set_port (target, portnum);
  699. }
  700. }
  701. else {
  702. if ((end = memchr (src, ':', srclen)) != NULL) {
  703. /* This is either port number and ipv4 addr or ipv6 addr */
  704. /* Search for another semicolon */
  705. if (memchr (end + 1, ':', srclen - (end - src + 1)) &&
  706. rspamd_parse_inet_address_ip6 (src, srclen, &su.s6.sin6_addr)) {
  707. rspamd_inet_address_v6_maybe_map_static (&su.s6, target);
  708. ret = TRUE;
  709. }
  710. else {
  711. /* Not ipv6, so try ip:port */
  712. iplen = end - src;
  713. if (iplen >= sizeof (ipbuf) || iplen <= 1) {
  714. return FALSE;
  715. }
  716. else {
  717. rspamd_strlcpy (ipbuf, src, iplen + 1);
  718. }
  719. if (rspamd_parse_inet_address_ip4 (ipbuf, iplen,
  720. &su.s4.sin_addr)) {
  721. memcpy (&target->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
  722. sizeof (struct in_addr));
  723. target->af = AF_INET;
  724. target->slen = sizeof (target->u.in.addr.s4);
  725. rspamd_strtoul (end + 1, srclen - iplen - 1, &portnum);
  726. rspamd_inet_address_set_port (target, portnum);
  727. ret = TRUE;
  728. }
  729. }
  730. }
  731. else {
  732. if (rspamd_parse_inet_address_ip4 (src, srclen, &su.s4.sin_addr)) {
  733. memcpy (&target->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
  734. sizeof (struct in_addr));
  735. target->af = AF_INET;
  736. target->slen = sizeof (target->u.in.addr.s4);
  737. ret = TRUE;
  738. }
  739. else if (rspamd_parse_inet_address_ip6 (src, srclen,
  740. &su.s6.sin6_addr)) {
  741. rspamd_inet_address_v6_maybe_map_static (&su.s6, target);
  742. ret = TRUE;
  743. }
  744. }
  745. }
  746. return ret;
  747. }
  748. const char *
  749. rspamd_inet_address_to_string (const rspamd_inet_addr_t *addr)
  750. {
  751. static char addr_str[INET6_ADDRSTRLEN + 1];
  752. if (addr == NULL) {
  753. return "<empty inet address>";
  754. }
  755. switch (addr->af) {
  756. case AF_INET:
  757. return inet_ntop (addr->af, &addr->u.in.addr.s4.sin_addr, addr_str,
  758. sizeof (addr_str));
  759. case AF_INET6:
  760. return inet_ntop (addr->af, &addr->u.in.addr.s6.sin6_addr, addr_str,
  761. sizeof (addr_str));
  762. case AF_UNIX:
  763. return addr->u.un->addr.sun_path;
  764. }
  765. return "undefined";
  766. }
  767. const char *
  768. rspamd_inet_address_to_string_pretty (const rspamd_inet_addr_t *addr)
  769. {
  770. static char addr_str[PATH_MAX + 5];
  771. if (addr == NULL) {
  772. return "<empty inet address>";
  773. }
  774. switch (addr->af) {
  775. case AF_INET:
  776. rspamd_snprintf (addr_str, sizeof (addr_str), "%s:%d",
  777. rspamd_inet_address_to_string (addr),
  778. rspamd_inet_address_get_port (addr));
  779. break;
  780. case AF_INET6:
  781. rspamd_snprintf (addr_str, sizeof (addr_str), "[%s]:%d",
  782. rspamd_inet_address_to_string (addr),
  783. rspamd_inet_address_get_port (addr));
  784. break;
  785. case AF_UNIX:
  786. rspamd_snprintf (addr_str, sizeof (addr_str), "unix:%s",
  787. rspamd_inet_address_to_string (addr));
  788. break;
  789. }
  790. return addr_str;
  791. }
  792. uint16_t
  793. rspamd_inet_address_get_port (const rspamd_inet_addr_t *addr)
  794. {
  795. switch (addr->af) {
  796. case AF_INET:
  797. return ntohs (addr->u.in.addr.s4.sin_port);
  798. case AF_INET6:
  799. return ntohs (addr->u.in.addr.s6.sin6_port);
  800. }
  801. return 0;
  802. }
  803. void
  804. rspamd_inet_address_set_port (rspamd_inet_addr_t *addr, uint16_t port)
  805. {
  806. switch (addr->af) {
  807. case AF_INET:
  808. addr->u.in.addr.s4.sin_port = htons (port);
  809. break;
  810. case AF_INET6:
  811. addr->u.in.addr.s6.sin6_port = htons (port);
  812. break;
  813. }
  814. }
  815. int
  816. rspamd_inet_address_connect (const rspamd_inet_addr_t *addr, gint type,
  817. gboolean async)
  818. {
  819. int fd, r;
  820. const struct sockaddr *sa;
  821. if (addr == NULL) {
  822. return -1;
  823. }
  824. fd = rspamd_socket_create (addr->af, type, 0, async);
  825. if (fd == -1) {
  826. return -1;
  827. }
  828. if (addr->af == AF_UNIX) {
  829. sa = (const struct sockaddr *)&addr->u.un->addr;
  830. }
  831. else {
  832. sa = &addr->u.in.addr.sa;
  833. }
  834. r = connect (fd, sa, addr->slen);
  835. if (r == -1) {
  836. if (!async || errno != EINPROGRESS) {
  837. close (fd);
  838. msg_warn ("connect %s failed: %d, '%s'",
  839. rspamd_inet_address_to_string_pretty (addr),
  840. errno, strerror (errno));
  841. return -1;
  842. }
  843. }
  844. return fd;
  845. }
  846. int
  847. rspamd_inet_address_listen (const rspamd_inet_addr_t *addr, gint type,
  848. gboolean async)
  849. {
  850. gint fd, r;
  851. gint on = 1;
  852. const struct sockaddr *sa;
  853. const char *path;
  854. if (addr == NULL) {
  855. return -1;
  856. }
  857. fd = rspamd_socket_create (addr->af, type, 0, async);
  858. if (fd == -1) {
  859. return -1;
  860. }
  861. if (addr->af == AF_UNIX && access (addr->u.un->addr.sun_path, W_OK) != -1) {
  862. /* Unlink old socket */
  863. (void)unlink (addr->u.un->addr.sun_path);
  864. }
  865. if (addr->af == AF_UNIX) {
  866. sa = (const struct sockaddr *)&addr->u.un->addr;
  867. }
  868. else {
  869. sa = &addr->u.in.addr.sa;
  870. }
  871. (void)setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (gint));
  872. #ifdef HAVE_IPV6_V6ONLY
  873. if (addr->af == AF_INET6) {
  874. /* We need to set this flag to avoid errors */
  875. on = 1;
  876. #ifdef SOL_IPV6
  877. (void)setsockopt (fd, SOL_IPV6, IPV6_V6ONLY, (const void *)&on, sizeof (gint));
  878. #elif defined(IPPROTO_IPV6)
  879. (void)setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&on, sizeof (gint));
  880. #endif
  881. }
  882. #endif
  883. r = bind (fd, sa, addr->slen);
  884. if (r == -1) {
  885. if (!async || errno != EINPROGRESS) {
  886. close (fd);
  887. msg_warn ("bind %s failed: %d, '%s'",
  888. rspamd_inet_address_to_string_pretty (addr),
  889. errno,
  890. strerror (errno));
  891. return -1;
  892. }
  893. }
  894. if (type != (int)SOCK_DGRAM) {
  895. if (addr->af == AF_UNIX) {
  896. path = addr->u.un->addr.sun_path;
  897. /* Try to set mode and owner */
  898. if (addr->u.un->owner != (uid_t)-1 || addr->u.un->group != (gid_t)-1) {
  899. if (chown (path, addr->u.un->owner, addr->u.un->group) == -1) {
  900. msg_info ("cannot change owner for %s to %d:%d: %s",
  901. path, addr->u.un->owner, addr->u.un->group,
  902. strerror (errno));
  903. }
  904. }
  905. if (chmod (path, addr->u.un->mode) == -1) {
  906. msg_info ("cannot change mode for %s to %od %s",
  907. path, addr->u.un->mode, strerror (errno));
  908. }
  909. }
  910. r = listen (fd, -1);
  911. if (r == -1) {
  912. msg_warn ("listen %s failed: %d, '%s'",
  913. rspamd_inet_address_to_string_pretty (addr),
  914. errno, strerror (errno));
  915. close (fd);
  916. return -1;
  917. }
  918. }
  919. return fd;
  920. }
  921. gssize
  922. rspamd_inet_address_recvfrom (gint fd, void *buf, gsize len, gint fl,
  923. rspamd_inet_addr_t **target)
  924. {
  925. gssize ret;
  926. union sa_union su;
  927. socklen_t slen = sizeof (su);
  928. rspamd_inet_addr_t *addr = NULL;
  929. if ((ret = recvfrom (fd, buf, len, fl, &su.sa, &slen)) == -1) {
  930. if (target) {
  931. *target = NULL;
  932. }
  933. return -1;
  934. }
  935. if (target) {
  936. addr = rspamd_inet_addr_create (su.sa.sa_family);
  937. addr->slen = slen;
  938. if (addr->af == AF_UNIX) {
  939. addr->u.un = g_malloc (sizeof (*addr->u.un));
  940. memcpy (&addr->u.un->addr, &su.su, sizeof (struct sockaddr_un));
  941. }
  942. else {
  943. memcpy (&addr->u.in.addr, &su.sa, MIN (slen, sizeof (addr->u.in.addr)));
  944. }
  945. *target = addr;
  946. }
  947. return (ret);
  948. }
  949. gssize
  950. rspamd_inet_address_sendto (gint fd, const void *buf, gsize len, gint fl,
  951. const rspamd_inet_addr_t *addr)
  952. {
  953. gssize r;
  954. const struct sockaddr *sa;
  955. if (addr == NULL) {
  956. return -1;
  957. }
  958. if (addr->af == AF_UNIX) {
  959. sa = (struct sockaddr *)&addr->u.un->addr;
  960. }
  961. else {
  962. sa = &addr->u.in.addr.sa;
  963. }
  964. r = sendto (fd, buf, len, fl, sa, addr->slen);
  965. return r;
  966. }
  967. static gboolean
  968. rspamd_check_port_priority (const char *line, guint default_port,
  969. guint *priority, gchar *out,
  970. gsize outlen, rspamd_mempool_t *pool)
  971. {
  972. guint real_port = default_port, real_priority = 0;
  973. gchar *err_str, *err_str_prio;
  974. if (line && line[0] == ':') {
  975. errno = 0;
  976. real_port = strtoul (line + 1, &err_str, 10);
  977. if (err_str && *err_str == ':') {
  978. /* We have priority */
  979. real_priority = strtoul (err_str + 1, &err_str_prio, 10);
  980. if (err_str_prio && *err_str_prio != '\0') {
  981. msg_err_pool_check (
  982. "cannot parse priority: %s, at symbol %c, error: %s",
  983. line,
  984. *err_str_prio,
  985. strerror (errno));
  986. return FALSE;
  987. }
  988. }
  989. else if (err_str && *err_str != '\0') {
  990. msg_err_pool_check (
  991. "cannot parse port: %s, at symbol %c, error: %s",
  992. line,
  993. *err_str,
  994. strerror (errno));
  995. return FALSE;
  996. }
  997. }
  998. if (priority) {
  999. *priority = real_priority;
  1000. }
  1001. rspamd_snprintf (out, outlen, "%ud", real_port);
  1002. return TRUE;
  1003. }
  1004. static gboolean
  1005. rspamd_resolve_addrs (const char *begin, size_t len, GPtrArray **addrs,
  1006. const gchar *portbuf, gint flags,
  1007. rspamd_mempool_t *pool)
  1008. {
  1009. struct addrinfo hints, *res, *cur;
  1010. rspamd_inet_addr_t *cur_addr = NULL;
  1011. gint r, addr_cnt;
  1012. gchar *addr_cpy = NULL;
  1013. rspamd_ip_check_ipv6 ();
  1014. if (rspamd_parse_inet_address (&cur_addr, begin, len)) {
  1015. if (*addrs == NULL) {
  1016. *addrs = g_ptr_array_new_full (1,
  1017. (GDestroyNotify) rspamd_inet_address_free);
  1018. if (pool != NULL) {
  1019. rspamd_mempool_add_destructor (pool,
  1020. rspamd_ptr_array_free_hard, *addrs);
  1021. }
  1022. }
  1023. rspamd_inet_address_set_port (cur_addr, strtoul (portbuf, NULL, 10));
  1024. g_ptr_array_add (*addrs, cur_addr);
  1025. }
  1026. else {
  1027. memset (&hints, 0, sizeof (hints));
  1028. hints.ai_socktype = SOCK_STREAM; /* Type of the socket */
  1029. hints.ai_flags = AI_NUMERICSERV|flags;
  1030. if (len > 0) {
  1031. if (pool) {
  1032. addr_cpy = rspamd_mempool_alloc (pool, len + 1);
  1033. }
  1034. else {
  1035. addr_cpy = g_malloc (len + 1);
  1036. }
  1037. rspamd_strlcpy (addr_cpy, begin, len + 1);
  1038. }
  1039. /* Otherwise it will be NULL */
  1040. if (ipv6_status == RSPAMD_IPV6_SUPPORTED) {
  1041. hints.ai_family = AF_UNSPEC;
  1042. }
  1043. else {
  1044. hints.ai_family = AF_INET;
  1045. }
  1046. if ((r = getaddrinfo (addr_cpy, portbuf, &hints, &res)) == 0) {
  1047. /* Now copy up to max_addrs of addresses */
  1048. addr_cnt = 0;
  1049. cur = res;
  1050. while (cur) {
  1051. cur = cur->ai_next;
  1052. addr_cnt ++;
  1053. }
  1054. if (*addrs == NULL) {
  1055. *addrs = g_ptr_array_new_full (addr_cnt,
  1056. (GDestroyNotify) rspamd_inet_address_free);
  1057. if (pool != NULL) {
  1058. rspamd_mempool_add_destructor (pool,
  1059. rspamd_ptr_array_free_hard, *addrs);
  1060. }
  1061. }
  1062. cur = res;
  1063. while (cur) {
  1064. cur_addr = rspamd_inet_address_from_sa (cur->ai_addr,
  1065. cur->ai_addrlen);
  1066. if (cur_addr != NULL) {
  1067. g_ptr_array_add (*addrs, cur_addr);
  1068. }
  1069. cur = cur->ai_next;
  1070. }
  1071. freeaddrinfo (res);
  1072. }
  1073. else if (addr_cpy) {
  1074. msg_err_pool_check ("address resolution for %s failed: %s",
  1075. addr_cpy,
  1076. gai_strerror (r));
  1077. if (pool == NULL) {
  1078. g_free (addr_cpy);
  1079. }
  1080. return FALSE;
  1081. }
  1082. else {
  1083. /* Should never ever happen */
  1084. g_assert (0);
  1085. }
  1086. }
  1087. return TRUE;
  1088. }
  1089. gboolean
  1090. rspamd_parse_host_port_priority (const gchar *str,
  1091. GPtrArray **addrs,
  1092. guint *priority,
  1093. gchar **name_ptr,
  1094. guint default_port,
  1095. rspamd_mempool_t *pool)
  1096. {
  1097. gchar portbuf[8];
  1098. const gchar *p, *name = NULL;
  1099. gsize namelen;
  1100. rspamd_inet_addr_t *cur_addr = NULL;
  1101. /*
  1102. * In this function, we can have several possibilities:
  1103. * 1) Unix socket: check for '.' or '/' at the begin of string
  1104. * 2) \[ipv6\]: check for '[' at the beginning
  1105. * 3) '*': means listening on any address
  1106. * 4) ip|host[:port[:priority]]
  1107. */
  1108. if (str[0] == '*') {
  1109. if (!rspamd_check_port_priority (str + 1, default_port, priority,
  1110. portbuf, sizeof (portbuf), pool)) {
  1111. return FALSE;
  1112. }
  1113. if (!rspamd_resolve_addrs (str, 0, addrs, portbuf, AI_PASSIVE, pool)) {
  1114. return FALSE;
  1115. }
  1116. name = "*";
  1117. namelen = 1;
  1118. }
  1119. else if (str[0] == '[') {
  1120. /* This is braced IPv6 address */
  1121. p = strchr (str, ']');
  1122. if (p == NULL) {
  1123. msg_err_pool_check ("cannot parse address definition %s: %s",
  1124. str,
  1125. strerror (EINVAL));
  1126. return FALSE;
  1127. }
  1128. name = str + 1;
  1129. namelen = p - str - 1;
  1130. if (!rspamd_check_port_priority (p + 1, default_port, priority, portbuf,
  1131. sizeof (portbuf), pool)) {
  1132. return FALSE;
  1133. }
  1134. if (!rspamd_resolve_addrs (name, namelen, addrs,
  1135. portbuf, 0, pool)) {
  1136. return FALSE;
  1137. }
  1138. }
  1139. else if (str[0] == '/' || str[0] == '.') {
  1140. /* Special case of unix socket, as getaddrinfo cannot deal with them */
  1141. if (*addrs == NULL) {
  1142. *addrs = g_ptr_array_new_full (1,
  1143. (GDestroyNotify) rspamd_inet_address_free);
  1144. if (pool != NULL) {
  1145. rspamd_mempool_add_destructor (pool,
  1146. rspamd_ptr_array_free_hard, *addrs);
  1147. }
  1148. }
  1149. if (!rspamd_parse_inet_address (&cur_addr, str, 0)) {
  1150. msg_err_pool_check ("cannot parse unix socket definition %s: %s",
  1151. str,
  1152. strerror (errno));
  1153. return FALSE;
  1154. }
  1155. g_ptr_array_add (*addrs, cur_addr);
  1156. name = str;
  1157. namelen = strlen (str);
  1158. }
  1159. else {
  1160. p = strchr (str, ':');
  1161. if (p == NULL) {
  1162. /* Just address or IP */
  1163. name = str;
  1164. namelen = strlen (str);
  1165. rspamd_check_port_priority ("", default_port, priority, portbuf,
  1166. sizeof (portbuf), pool);
  1167. if (!rspamd_resolve_addrs (name, namelen, addrs,
  1168. portbuf, 0, pool)) {
  1169. return FALSE;
  1170. }
  1171. }
  1172. else {
  1173. name = str;
  1174. namelen = p - str;
  1175. if (!rspamd_check_port_priority (p, default_port, priority, portbuf,
  1176. sizeof (portbuf), pool)) {
  1177. return FALSE;
  1178. }
  1179. if (!rspamd_resolve_addrs (str, p - str, addrs,
  1180. portbuf, 0, pool)) {
  1181. return FALSE;
  1182. }
  1183. }
  1184. }
  1185. if (name_ptr != NULL) {
  1186. if (pool) {
  1187. *name_ptr = rspamd_mempool_alloc (pool, namelen + 1);
  1188. }
  1189. else {
  1190. *name_ptr = g_malloc (namelen + 1);
  1191. }
  1192. rspamd_strlcpy (*name_ptr, name, namelen + 1);
  1193. }
  1194. return TRUE;
  1195. }
  1196. guchar*
  1197. rspamd_inet_address_get_hash_key (const rspamd_inet_addr_t *addr, guint *klen)
  1198. {
  1199. guchar *res = NULL;
  1200. static struct in_addr local = {INADDR_LOOPBACK};
  1201. g_assert (addr != NULL);
  1202. g_assert (klen != NULL);
  1203. if (addr->af == AF_INET) {
  1204. *klen = sizeof (struct in_addr);
  1205. res = (guchar *)&addr->u.in.addr.s4.sin_addr;
  1206. }
  1207. else if (addr->af == AF_INET6) {
  1208. *klen = sizeof (struct in6_addr);
  1209. res = (guchar *)&addr->u.in.addr.s6.sin6_addr;
  1210. }
  1211. else if (addr->af == AF_UNIX) {
  1212. *klen = sizeof (struct in_addr);
  1213. res = (guchar *)&local;
  1214. }
  1215. else {
  1216. *klen = 0;
  1217. res = NULL;
  1218. }
  1219. return res;
  1220. }
  1221. rspamd_inet_addr_t *
  1222. rspamd_inet_address_new (int af, const void *init)
  1223. {
  1224. rspamd_inet_addr_t *addr;
  1225. addr = rspamd_inet_addr_create (af);
  1226. if (init != NULL) {
  1227. if (af == AF_UNIX) {
  1228. /* Init is a path */
  1229. rspamd_strlcpy (addr->u.un->addr.sun_path, init,
  1230. sizeof (addr->u.un->addr.sun_path));
  1231. #if defined(FREEBSD) || defined(__APPLE__)
  1232. addr->u.un->addr.sun_len = SUN_LEN (&addr->u.un->addr);
  1233. #endif
  1234. }
  1235. else if (af == AF_INET) {
  1236. memcpy (&addr->u.in.addr.s4.sin_addr, init, sizeof (struct in_addr));
  1237. }
  1238. else if (af == AF_INET6) {
  1239. memcpy (&addr->u.in.addr.s6.sin6_addr, init, sizeof (struct in6_addr));
  1240. }
  1241. }
  1242. return addr;
  1243. }
  1244. rspamd_inet_addr_t *
  1245. rspamd_inet_address_from_sa (const struct sockaddr *sa, socklen_t slen)
  1246. {
  1247. rspamd_inet_addr_t *addr;
  1248. g_assert (sa != NULL);
  1249. g_assert (slen >= sizeof (struct sockaddr));
  1250. addr = rspamd_inet_addr_create (sa->sa_family);
  1251. if (sa->sa_family == AF_UNIX) {
  1252. /* Init is a path */
  1253. const struct sockaddr_un *un = (const struct sockaddr_un *)sa;
  1254. g_assert (slen >= SUN_LEN (un));
  1255. rspamd_strlcpy (addr->u.un->addr.sun_path, un->sun_path,
  1256. sizeof (addr->u.un->addr.sun_path));
  1257. #if defined(FREEBSD) || defined(__APPLE__)
  1258. addr->u.un->addr.sun_len = un->sun_len;
  1259. #endif
  1260. }
  1261. else if (sa->sa_family == AF_INET) {
  1262. g_assert (slen >= sizeof (struct sockaddr_in));
  1263. memcpy (&addr->u.in.addr.s4, sa, sizeof (struct sockaddr_in));
  1264. }
  1265. else if (sa->sa_family == AF_INET6) {
  1266. g_assert (slen >= sizeof (struct sockaddr_in6));
  1267. memcpy (&addr->u.in.addr.s6, sa, sizeof (struct sockaddr_in6));
  1268. }
  1269. else {
  1270. /* XXX: currently we cannot deal with other AF */
  1271. g_assert (0);
  1272. }
  1273. return addr;
  1274. }
  1275. rspamd_inet_addr_t *
  1276. rspamd_inet_address_from_rnds (const struct rdns_reply_entry *rep)
  1277. {
  1278. rspamd_inet_addr_t *addr = NULL;
  1279. g_assert (rep != NULL);
  1280. if (rep->type == RDNS_REQUEST_A) {
  1281. addr = rspamd_inet_addr_create (AF_INET);
  1282. memcpy (&addr->u.in.addr.s4.sin_addr, &rep->content.a.addr,
  1283. sizeof (struct in_addr));
  1284. }
  1285. else if (rep->type == RDNS_REQUEST_AAAA) {
  1286. addr = rspamd_inet_addr_create (AF_INET6);
  1287. memcpy (&addr->u.in.addr.s6.sin6_addr, &rep->content.aaa.addr,
  1288. sizeof (struct in6_addr));
  1289. }
  1290. return addr;
  1291. }
  1292. void
  1293. rspamd_inet_address_apply_mask (rspamd_inet_addr_t *addr, guint mask)
  1294. {
  1295. guint32 umsk, *p;
  1296. if (mask > 0 && addr != NULL) {
  1297. if (addr->af == AF_INET && mask <= 32) {
  1298. umsk = htonl (G_MAXUINT32 << (32 - mask));
  1299. addr->u.in.addr.s4.sin_addr.s_addr &= umsk;
  1300. }
  1301. else if (addr->af == AF_INET6 && mask <= 128) {
  1302. p = (uint32_t *)&addr->u.in.addr.s6.sin6_addr;
  1303. mask = 128 - mask;
  1304. p += 3;
  1305. for (;;) {
  1306. if (mask >= 32) {
  1307. mask -= 32;
  1308. *p = 0;
  1309. }
  1310. else {
  1311. umsk = htonl (G_MAXUINT32 << mask);
  1312. *p &= umsk;
  1313. break;
  1314. }
  1315. p --;
  1316. }
  1317. }
  1318. }
  1319. }
  1320. static gint
  1321. rspamd_inet_address_af_order (const rspamd_inet_addr_t *addr)
  1322. {
  1323. int ret;
  1324. switch (addr->af) {
  1325. case AF_UNIX:
  1326. ret = 2;
  1327. break;
  1328. case AF_INET:
  1329. ret = 1;
  1330. break;
  1331. default:
  1332. ret = 0;
  1333. break;
  1334. }
  1335. return ret;
  1336. }
  1337. gint
  1338. rspamd_inet_address_compare (const rspamd_inet_addr_t *a1,
  1339. const rspamd_inet_addr_t *a2)
  1340. {
  1341. g_assert (a1 != NULL);
  1342. g_assert (a2 != NULL);
  1343. if (a1->af != a2->af) {
  1344. return (rspamd_inet_address_af_order (a2) -
  1345. rspamd_inet_address_af_order (a1));
  1346. }
  1347. else {
  1348. switch (a1->af) {
  1349. case AF_INET:
  1350. return memcmp (&a1->u.in.addr.s4.sin_addr,
  1351. &a2->u.in.addr.s4.sin_addr, sizeof (struct in_addr));
  1352. case AF_INET6:
  1353. return memcmp (&a1->u.in.addr.s6.sin6_addr,
  1354. &a2->u.in.addr.s6.sin6_addr, sizeof (struct in6_addr));
  1355. case AF_UNIX:
  1356. return strncmp (a1->u.un->addr.sun_path,
  1357. a2->u.un->addr.sun_path, sizeof (a1->u.un->addr.sun_path));
  1358. default:
  1359. return memcmp (&a1->u.in, &a2->u.in, sizeof (a1->u.in));
  1360. }
  1361. }
  1362. return 0;
  1363. }
  1364. gint
  1365. rspamd_inet_address_compare_ptr (gconstpointer a1,
  1366. gconstpointer a2)
  1367. {
  1368. const rspamd_inet_addr_t **i1 = (const rspamd_inet_addr_t **)a1,
  1369. **i2 = (const rspamd_inet_addr_t **)a2;
  1370. return rspamd_inet_address_compare (*i1, *i2);
  1371. }
  1372. rspamd_inet_addr_t *
  1373. rspamd_inet_address_copy (const rspamd_inet_addr_t *addr)
  1374. {
  1375. rspamd_inet_addr_t *n;
  1376. if (addr == NULL) {
  1377. return NULL;
  1378. }
  1379. n = rspamd_inet_addr_create (addr->af);
  1380. if (n->af == AF_UNIX) {
  1381. memcpy (n->u.un, addr->u.un, sizeof (*addr->u.un));
  1382. }
  1383. else {
  1384. memcpy (&n->u.in, &addr->u.in, sizeof (addr->u.in));
  1385. }
  1386. return n;
  1387. }
  1388. gint
  1389. rspamd_inet_address_get_af (const rspamd_inet_addr_t *addr)
  1390. {
  1391. g_assert (addr != NULL);
  1392. return addr->af;
  1393. }
  1394. guint
  1395. rspamd_inet_address_hash (gconstpointer a)
  1396. {
  1397. const rspamd_inet_addr_t *addr = a;
  1398. rspamd_cryptobox_fast_hash_state_t st;
  1399. rspamd_cryptobox_fast_hash_init (&st, rspamd_hash_seed ());
  1400. rspamd_cryptobox_fast_hash_update (&st, &addr->af, sizeof (addr->af));
  1401. if (addr->af == AF_UNIX && addr->u.un) {
  1402. rspamd_cryptobox_fast_hash_update (&st, addr->u.un, sizeof (*addr->u.un));
  1403. }
  1404. else {
  1405. /* We ignore port part here */
  1406. if (addr->af == AF_INET) {
  1407. rspamd_cryptobox_fast_hash_update (&st, &addr->u.in.addr.s4.sin_addr,
  1408. sizeof (addr->u.in.addr.s4.sin_addr));
  1409. }
  1410. else {
  1411. rspamd_cryptobox_fast_hash_update (&st, &addr->u.in.addr.s6.sin6_addr,
  1412. sizeof (addr->u.in.addr.s6.sin6_addr));
  1413. }
  1414. }
  1415. return rspamd_cryptobox_fast_hash_final (&st);
  1416. }
  1417. gboolean
  1418. rspamd_inet_address_equal (gconstpointer a, gconstpointer b)
  1419. {
  1420. const rspamd_inet_addr_t *a1 = a, *a2 = b;
  1421. return rspamd_inet_address_compare (a1, a2) == 0;
  1422. }
  1423. #ifndef IN6_IS_ADDR_LOOPBACK
  1424. #define IN6_IS_ADDR_LOOPBACK(a) \
  1425. ((*(const __uint32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
  1426. (*(const __uint32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
  1427. (*(const __uint32_t *)(const void *)(&(a)->s6_addr[8]) == 0) && \
  1428. (*(const __uint32_t *)(const void *)(&(a)->s6_addr[12]) == ntohl(1)))
  1429. #endif
  1430. #ifndef IN6_IS_ADDR_LINKLOCAL
  1431. #define IN6_IS_ADDR_LINKLOCAL(a) \
  1432. (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0x80))
  1433. #endif
  1434. #ifndef IN6_IS_ADDR_SITELOCAL
  1435. #define IN6_IS_ADDR_SITELOCAL(a) \
  1436. (((a)->s6_addr[0] == 0xfe) && (((a)->s6_addr[1] & 0xc0) == 0xc0))
  1437. #endif
  1438. gboolean
  1439. rspamd_inet_address_is_local (const rspamd_inet_addr_t *addr,
  1440. gboolean check_laddrs)
  1441. {
  1442. if (addr == NULL) {
  1443. return FALSE;
  1444. }
  1445. if (addr->af == AF_UNIX) {
  1446. /* Always true for unix sockets */
  1447. return TRUE;
  1448. }
  1449. else {
  1450. if (addr->af == AF_INET) {
  1451. if ((ntohl (addr->u.in.addr.s4.sin_addr.s_addr) & 0xff000000)
  1452. == 0x7f000000) {
  1453. return TRUE;
  1454. }
  1455. }
  1456. else if (addr->af == AF_INET6) {
  1457. if (IN6_IS_ADDR_LOOPBACK (&addr->u.in.addr.s6.sin6_addr) ||
  1458. IN6_IS_ADDR_LINKLOCAL (&addr->u.in.addr.s6.sin6_addr) ||
  1459. IN6_IS_ADDR_SITELOCAL (&addr->u.in.addr.s6.sin6_addr)) {
  1460. return TRUE;
  1461. }
  1462. }
  1463. if (check_laddrs && local_addrs) {
  1464. if (rspamd_match_radix_map_addr (local_addrs, addr) != NULL) {
  1465. return TRUE;
  1466. }
  1467. }
  1468. }
  1469. return FALSE;
  1470. }
  1471. struct rspamd_radix_map_helper **
  1472. rspamd_inet_library_init (void)
  1473. {
  1474. return &local_addrs;
  1475. }
  1476. void
  1477. rspamd_inet_library_destroy (void)
  1478. {
  1479. /* Ugly: local_addrs will actually be freed by config object */
  1480. }
  1481. gsize
  1482. rspamd_inet_address_storage_size (void)
  1483. {
  1484. return sizeof (rspamd_inet_addr_t);
  1485. }