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 45KB

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