address.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994
  1. /*
  2. * Part of Scheme 48 1.9. See file COPYING for notices and license.
  3. *
  4. * Authors: Mike Sperber, Marcus Crestani
  5. */
  6. #define NO_OLD_FFI 1
  7. /*
  8. * Socket addresses
  9. */
  10. /* Main source: RFC 3493 - Basic Socket Interface Extensions for IPv6 */
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #ifdef _WIN32
  14. #include <winsock2.h>
  15. #include <mswsock.h>
  16. #include <windows.h>
  17. #include <ws2tcpip.h>
  18. #include <iphlpapi.h>
  19. #define HAVE_THREADS
  20. #define DECLARE_THREAD_PROC(name, param_name) \
  21. DWORD WINAPI name(LPVOID param_name)
  22. #define EXIT_THREAD_PROC() do { ExitThread(0); return 0; } while (0)
  23. typedef HANDLE thread_type;
  24. #define START_THREAD(desc, name, arg) \
  25. ((desc = CreateThread(NULL, 4096, (LPTHREAD_START_ROUTINE) name, (LPVOID) arg, 0, NULL)) == NULL)
  26. #define DETACH_THREAD(desc) ;
  27. #else
  28. #include <sys/types.h>
  29. #include <sys/socket.h>
  30. #include <netdb.h>
  31. #include <netinet/in.h>
  32. #include <arpa/inet.h>
  33. #include <net/if.h>
  34. #include <sys/un.h>
  35. #include "sysdep.h"
  36. #ifdef HAVE_PTHREAD_H
  37. #include <pthread.h>
  38. #define HAVE_THREADS
  39. #define DECLARE_THREAD_PROC(name, param_name) \
  40. void* name(void* param_name)
  41. #define EXIT_THREAD_PROC() do { return NULL; } while (0)
  42. typedef pthread_t thread_type;
  43. #define START_THREAD(desc, name, arg) \
  44. pthread_create(&desc, NULL, name, (void*) arg)
  45. #define DETACH_THREAD(desc) pthread_detach(desc)
  46. #endif
  47. #endif
  48. #include <errno.h>
  49. #include <scheme48.h>
  50. #include "address.h"
  51. static int
  52. maybe_extract_latin1_string(s48_call_t call, s48_ref_t sch_str, char* buffer, size_t size)
  53. {
  54. if (s48_string_length_2(call, sch_str) > (size - 1))
  55. return 0;
  56. s48_copy_string_to_latin_1_2(call, sch_str, buffer);
  57. buffer[s48_string_length_2(call, sch_str)] = '\0';
  58. return 1;
  59. }
  60. static char*
  61. maybe_extract_fresh_latin1_string(s48_call_t call, s48_ref_t sch_str, size_t size)
  62. {
  63. char *result;
  64. if (s48_string_length_2(call, sch_str) > (size - 1))
  65. return NULL;
  66. result = malloc(size);
  67. if (result == NULL)
  68. s48_out_of_memory_error_2(call);
  69. s48_copy_string_to_latin_1_2(call, sch_str, result);
  70. result[s48_string_length_2(call, sch_str)] = '\0';
  71. return result;
  72. }
  73. /* The C code knows about these constants. */
  74. sa_family_t
  75. s48_extract_af(s48_call_t call, s48_ref_t sch_af_val)
  76. {
  77. long af_val = s48_extract_long_2(call, sch_af_val);
  78. if (af_val > 100) /* unknown address family */
  79. return af_val - 100;
  80. else
  81. switch (af_val)
  82. {
  83. case 0:
  84. return AF_INET;
  85. case 1:
  86. return AF_INET6;
  87. case 2:
  88. return AF_UNIX;
  89. case 3 :
  90. return AF_UNSPEC;
  91. }
  92. }
  93. s48_ref_t
  94. s48_enter_af(s48_call_t call, sa_family_t af)
  95. {
  96. switch(af)
  97. {
  98. case AF_INET:
  99. return s48_enter_long_as_fixnum_2(call, 0);
  100. case AF_INET6:
  101. return s48_enter_long_as_fixnum_2(call, 1);
  102. case AF_UNIX:
  103. return s48_enter_long_as_fixnum_2(call, 2);
  104. case AF_UNSPEC:
  105. return s48_enter_long_as_fixnum_2(call, 3);
  106. default:
  107. return s48_enter_long_as_fixnum_2(call, (int) af + 100);
  108. }
  109. }
  110. /* IPv4 addresses */
  111. static s48_ref_t
  112. enter_in_addr(s48_call_t call, const struct in_addr* addr)
  113. {
  114. return s48_enter_unsigned_long_2(call, ntohl(addr->s_addr));
  115. }
  116. static void
  117. extract_in_addr(s48_call_t call, s48_ref_t sch_addr, struct in_addr* addr)
  118. {
  119. addr->s_addr = htonl(s48_extract_unsigned_long_2(call, sch_addr));
  120. }
  121. static s48_ref_t
  122. s48_enter_sockaddr_in_raw(s48_call_t call, const struct sockaddr_in *saddr)
  123. {
  124. s48_ref_t sch_native = s48_make_value_2(call, struct sockaddr_in);
  125. memcpy(s48_extract_value_pointer_2(call, sch_native, void), saddr,
  126. sizeof(struct sockaddr_in));
  127. return sch_native;
  128. }
  129. static s48_ref_t
  130. s48_enter_sockaddr_in(s48_call_t call, const struct sockaddr_in *saddr)
  131. {
  132. s48_ref_t sch_saddr = s48_make_vector_2(call, 4, s48_unspecific_2(call));
  133. s48_vector_set_2(call, sch_saddr, 0, s48_enter_sockaddr_in_raw(call, saddr));
  134. s48_vector_set_2(call, sch_saddr, 1, s48_enter_af(call, AF_INET));
  135. s48_vector_set_2(call, sch_saddr, 2, s48_enter_long_as_fixnum_2(call, ntohs(saddr->sin_port)));
  136. s48_vector_set_2(call, sch_saddr, 3, enter_in_addr(call, &(saddr->sin_addr)));
  137. return sch_saddr;
  138. }
  139. static s48_ref_t
  140. s48_make_sockaddr_in_raw(s48_call_t call, s48_ref_t sch_in_addr, s48_ref_t sch_port)
  141. {
  142. struct sockaddr_in saddr;
  143. memset(&saddr, 0, sizeof(struct sockaddr_in));
  144. #ifdef SIN6_LEN
  145. /* sockaddr addresses either all have the length, or none has */
  146. saddr.sin_len = sizeof(struct sockaddr_in);
  147. #endif
  148. saddr.sin_family = AF_INET;
  149. saddr.sin_port = htons(s48_extract_long_2(call, sch_port));
  150. extract_in_addr(call, sch_in_addr, &(saddr.sin_addr));
  151. return s48_enter_sockaddr_in_raw(call, &saddr);
  152. }
  153. static s48_ref_t
  154. s48_get_inaddr_any(s48_call_t call)
  155. {
  156. struct in_addr addr;
  157. addr.s_addr = htonl(INADDR_ANY);
  158. return enter_in_addr(call, &addr);
  159. }
  160. static s48_ref_t
  161. s48_get_inaddr_broadcast(s48_call_t call)
  162. {
  163. struct in_addr addr;
  164. addr.s_addr = htonl(INADDR_BROADCAST);
  165. return enter_in_addr(call, &addr);
  166. }
  167. /* IPv6 addresses */
  168. s48_ref_t
  169. s48_enter_in6_addr(s48_call_t call, const struct in6_addr* addr)
  170. {
  171. s48_ref_t sch_addr = s48_make_byte_vector_2(call, 16);
  172. char* bytes = s48_extract_byte_vector_2(call, sch_addr);
  173. int i = 0;
  174. while (i < 16)
  175. {
  176. bytes[i] = (char) addr->s6_addr[i];
  177. ++i;
  178. }
  179. return sch_addr;
  180. }
  181. void
  182. s48_extract_in6_addr(s48_call_t call, s48_ref_t sch_addr, struct in6_addr* addr)
  183. {
  184. char* bytes = s48_extract_byte_vector_readonly_2(call, sch_addr);
  185. int i = 0;
  186. while (i < 16)
  187. {
  188. addr->s6_addr[i] = (uint8_t) bytes[i];
  189. ++i;
  190. }
  191. }
  192. static s48_ref_t
  193. s48_enter_sockaddr_in6_raw(s48_call_t call, const struct sockaddr_in6 *saddr)
  194. {
  195. s48_ref_t sch_native = s48_make_value_2(call, struct sockaddr_in6);
  196. memcpy(s48_extract_value_pointer_2(call, sch_native, void), saddr,
  197. sizeof(struct sockaddr_in6));
  198. return sch_native;
  199. }
  200. static s48_ref_t
  201. s48_enter_sockaddr_in6(s48_call_t call, const struct sockaddr_in6 *saddr)
  202. {
  203. s48_ref_t sch_saddr = s48_make_vector_2(call, 5, s48_unspecific_2(call));
  204. s48_vector_set_2(call, sch_saddr, 0, s48_enter_sockaddr_in6_raw(call, saddr));
  205. s48_vector_set_2(call, sch_saddr, 1, s48_enter_af(call, AF_INET6));
  206. s48_vector_set_2(call, sch_saddr, 2, s48_enter_long_as_fixnum_2(call, ntohs(saddr->sin6_port)));
  207. /* flowinfo is insignificant */
  208. s48_vector_set_2(call, sch_saddr, 3, s48_enter_in6_addr(call, &(saddr->sin6_addr)));
  209. s48_vector_set_2(call, sch_saddr, 4, s48_enter_unsigned_long_2(call, saddr->sin6_scope_id));
  210. return sch_saddr;
  211. }
  212. static s48_ref_t
  213. s48_make_sockaddr_in6_raw(s48_call_t call, s48_ref_t sch_addr, s48_ref_t sch_port,
  214. s48_ref_t sch_scope_id)
  215. {
  216. struct sockaddr_in6 saddr;
  217. memset(&saddr, 0, sizeof(struct sockaddr_in6));
  218. #ifdef SIN6_LEN
  219. saddr.sin6_len = sizeof(struct sockaddr_in6);
  220. #endif
  221. saddr.sin6_family = AF_INET6;
  222. saddr.sin6_port = htons(s48_extract_long_2(call, sch_port));
  223. saddr.sin6_flowinfo = 0;
  224. s48_extract_in6_addr(call, sch_addr, &(saddr.sin6_addr));
  225. saddr.sin6_scope_id = s48_extract_unsigned_long_2(call, sch_scope_id);
  226. return s48_enter_sockaddr_in6_raw(call, &saddr);
  227. }
  228. static s48_ref_t
  229. s48_get_in6addr_any(s48_call_t call)
  230. {
  231. return s48_enter_in6_addr(call, &in6addr_any);
  232. }
  233. static s48_ref_t
  234. s48_get_in6addr_loopback(s48_call_t call)
  235. {
  236. return s48_enter_in6_addr(call, &in6addr_loopback);
  237. }
  238. #ifdef SUN_LEN
  239. /* BSD 4.4 */
  240. #define SOCKADDR_UN_LEN(su) SUN_LEN(&su)
  241. #else
  242. #define SOCKADDR_UN_LEN(su) (sizeof(su) - sizeof((su).sun_path) + strlen((su).sun_path))
  243. #endif
  244. #ifndef _WIN32
  245. /* Unix domain addresses */
  246. static s48_ref_t
  247. s48_enter_sockaddr_un_raw(s48_call_t call, const struct sockaddr_un *saddr)
  248. {
  249. size_t len = SOCKADDR_UN_LEN(*saddr);
  250. s48_ref_t sch_native = s48_make_sized_value_2(call, len);
  251. memcpy(s48_extract_value_pointer_2(call, sch_native, void), saddr, len+1);
  252. return sch_native;
  253. }
  254. static s48_ref_t
  255. s48_make_sockaddr_un_raw(s48_call_t call, s48_ref_t sch_path)
  256. {
  257. struct sockaddr_un saddr;
  258. size_t max_path_len = sizeof(saddr) + ((char*)&(saddr.sun_path) - (char*)&saddr);
  259. s48_ref_t sch_native;
  260. memset(&saddr, 0, sizeof(struct sockaddr_un));
  261. if (s48_byte_vector_length_2(call, sch_path) > max_path_len)
  262. s48_assertion_violation_2(call, "s48_make_sockaddr_un_raw", "path too long", 1,
  263. sch_path);
  264. saddr.sun_family = AF_UNIX;
  265. strcpy(saddr.sun_path, s48_extract_byte_vector_readonly_2(call, sch_path));
  266. #ifdef SIN6_LEN
  267. saddr.sun_len = SUN_LEN(&saddr);
  268. #endif
  269. return s48_enter_sockaddr_un_raw(call, &saddr);
  270. }
  271. static s48_ref_t
  272. s48_enter_sockaddr_un(s48_call_t call, const struct sockaddr_un *saddr)
  273. {
  274. s48_ref_t sch_saddr = s48_make_vector_2(call, 3, s48_unspecific_2(call));
  275. s48_vector_set_2(call, sch_saddr, 0, s48_enter_sockaddr_un_raw(call, saddr));
  276. s48_vector_set_2(call, sch_saddr, 1, s48_enter_af(call, AF_UNIX));
  277. s48_vector_set_2(call, sch_saddr, 2, s48_enter_byte_string_2(call, (char*)saddr->sun_path));
  278. return sch_saddr;
  279. }
  280. #endif /* !_WIN32 */
  281. /* Generic addresses */
  282. static s48_ref_t
  283. s48_enter_sockaddr_unknown_raw(s48_call_t call, const struct sockaddr *saddr, socklen_t addrlen)
  284. {
  285. s48_ref_t sch_native = s48_make_sized_value_2(call, addrlen);
  286. memcpy(s48_extract_value_pointer_2(call, sch_native, void), saddr,
  287. addrlen);
  288. return sch_native;
  289. }
  290. s48_ref_t
  291. s48_enter_sockaddr(s48_call_t call, const struct sockaddr* saddr, socklen_t addrlen)
  292. {
  293. switch (saddr->sa_family)
  294. {
  295. case AF_INET:
  296. return s48_enter_sockaddr_in(call, (const struct sockaddr_in*) saddr);
  297. case AF_INET6:
  298. return s48_enter_sockaddr_in6(call, (const struct sockaddr_in6*) saddr);
  299. #ifndef _WIN32
  300. case AF_UNIX:
  301. return s48_enter_sockaddr_un(call, (const struct sockaddr_un*) saddr);
  302. #endif
  303. default:
  304. {
  305. s48_ref_t sch_saddr = s48_make_vector_2(call, 2, s48_unspecific_2(call));
  306. s48_vector_set_2(call, sch_saddr, 0, s48_enter_sockaddr_unknown_raw(call, saddr, addrlen));
  307. s48_vector_set_2(call, sch_saddr, 1, s48_enter_af(call, saddr->sa_family));
  308. return sch_saddr;
  309. }
  310. }
  311. }
  312. /* Interfaces */
  313. #ifndef _WIN32 /* supposedly available on Vista, so there's hope */
  314. /* note an error is indicated by 0 */
  315. static s48_ref_t
  316. s48_if_nametoindex(s48_call_t call, s48_ref_t sch_ifname)
  317. {
  318. char name[IF_NAMESIZE];
  319. if (!maybe_extract_latin1_string(call, sch_ifname, name, sizeof(name)))
  320. return s48_enter_long_as_fixnum_2(call, 0);
  321. return s48_enter_unsigned_long_2(call, if_nametoindex(name));
  322. }
  323. static s48_ref_t
  324. s48_if_indextoname(s48_call_t call, s48_ref_t sch_ifindex)
  325. {
  326. char ifname[IF_NAMESIZE];
  327. if (if_indextoname(s48_extract_unsigned_long_2(call, sch_ifindex), ifname) != NULL)
  328. return s48_enter_string_latin_1_2(call, ifname);
  329. else
  330. s48_os_error_2(call, "s48_if_indextoname", errno, 1, sch_ifindex);
  331. }
  332. /* Return a vector with alternating names and indices. */
  333. static s48_ref_t
  334. s48_if_nameindex(s48_call_t call)
  335. {
  336. s48_ref_t sch_table;
  337. struct if_nameindex *index = if_nameindex();
  338. int index_size;
  339. if (index == NULL)
  340. s48_os_error_2(call, "s48_if_nameindex", errno, 0);
  341. index_size = 0;
  342. {
  343. struct if_nameindex *p = index;
  344. while (p->if_index != 0)
  345. {
  346. ++p;
  347. ++index_size;
  348. }
  349. }
  350. sch_table = s48_make_vector_2(call, 2 * index_size, s48_unspecific_2(call));
  351. {
  352. int i = 0;
  353. while (i < index_size)
  354. {
  355. s48_vector_set_2(call, sch_table, i * 2,
  356. s48_enter_unsigned_long_2(call, index[i].if_index));
  357. s48_vector_set_2(call, sch_table, (i * 2) + 1,
  358. s48_enter_string_latin_1_2(call, index[i].if_name));
  359. ++i;
  360. }
  361. }
  362. if_freenameindex(index);
  363. return sch_table;
  364. }
  365. #endif
  366. /* Nodename translation */
  367. int
  368. s48_extract_socket_type(s48_call_t call, s48_ref_t sch_socktype)
  369. {
  370. long socktype_val = s48_extract_long_2(call, sch_socktype);
  371. if (socktype_val > 100)
  372. return socktype_val - 100;
  373. else
  374. switch (socktype_val)
  375. {
  376. case 0:
  377. return SOCK_STREAM;
  378. case 1:
  379. return SOCK_DGRAM;
  380. }
  381. }
  382. s48_ref_t
  383. s48_enter_socket_type(s48_call_t call, int socktype)
  384. {
  385. switch (socktype)
  386. {
  387. case SOCK_STREAM:
  388. return s48_enter_long_as_fixnum_2(call, 0);
  389. case SOCK_DGRAM:
  390. return s48_enter_long_as_fixnum_2(call, 1);
  391. default:
  392. return s48_enter_long_as_fixnum_2(call, (int) socktype + 100);
  393. }
  394. }
  395. static int
  396. extract_ai_flags(s48_call_t call, s48_ref_t sch_flags)
  397. {
  398. long flags = s48_extract_long_2(call, sch_flags);
  399. return (((flags & 0x01) ? AI_PASSIVE : 0)
  400. | ((flags & 0x02) ? AI_CANONNAME : 0)
  401. | ((flags & 0x04) ? AI_NUMERICHOST : 0));
  402. }
  403. static s48_ref_t
  404. enter_ai_flags(s48_call_t call, int flags)
  405. {
  406. return
  407. s48_enter_long_as_fixnum_2(call, ((flags & AI_PASSIVE) ? 0x01 : 0)
  408. | ((flags & AI_CANONNAME) ? 0x02 : 0)
  409. | ((flags & AI_NUMERICHOST) ? 0x04 : 0));
  410. }
  411. static int
  412. extract_ip_protocol(s48_call_t call, s48_ref_t sch_protocol)
  413. {
  414. long ip = s48_extract_long_2(call, sch_protocol);
  415. if (ip > 100)
  416. return ip - 100;
  417. else
  418. switch (ip)
  419. {
  420. case 0:
  421. return IPPROTO_IP;
  422. case 1:
  423. return IPPROTO_IPV6;
  424. case 2:
  425. return IPPROTO_ICMP;
  426. case 3:
  427. return IPPROTO_RAW;
  428. case 4:
  429. return IPPROTO_TCP;
  430. case 5:
  431. return IPPROTO_UDP;
  432. }
  433. }
  434. static s48_ref_t
  435. enter_ip_protocol(s48_call_t call, int protocol)
  436. {
  437. switch (protocol)
  438. {
  439. case IPPROTO_IP:
  440. return s48_enter_long_as_fixnum_2(call, 0);
  441. case IPPROTO_IPV6:
  442. return s48_enter_long_as_fixnum_2(call, 1);
  443. case IPPROTO_ICMP:
  444. return s48_enter_long_as_fixnum_2(call, 2);
  445. case IPPROTO_RAW:
  446. return s48_enter_long_as_fixnum_2(call, 3);
  447. case IPPROTO_TCP:
  448. return s48_enter_long_as_fixnum_2(call, 4);
  449. case IPPROTO_UDP:
  450. return s48_enter_long_as_fixnum_2(call, 5);
  451. default:
  452. return s48_enter_long_as_fixnum_2(call, protocol + 100);
  453. }
  454. }
  455. struct getaddrinfo_handshake
  456. {
  457. long event_uid;
  458. char* nodename;
  459. char* servname;
  460. struct addrinfo hints;
  461. int status;
  462. struct addrinfo* result;
  463. };
  464. static s48_ref_t
  465. enter_addrinfo(s48_call_t call, const struct addrinfo *ai)
  466. {
  467. s48_ref_t sch_ai = s48_make_vector_2(call, 5, s48_unspecific_2(call));
  468. s48_vector_set_2(call, sch_ai, 0, s48_enter_af(call, ai->ai_family));
  469. s48_vector_set_2(call, sch_ai, 1, s48_enter_socket_type(call, ai->ai_socktype));
  470. s48_vector_set_2(call, sch_ai, 2, enter_ip_protocol(call, ai->ai_protocol));
  471. s48_vector_set_2(call, sch_ai, 3,
  472. (ai->ai_canonname != NULL)
  473. ? s48_enter_string_latin_1_2(call, ai->ai_canonname) : s48_false_2(call));
  474. s48_vector_set_2(call, sch_ai, 4, s48_enter_sockaddr(call, ai->ai_addr, ai->ai_addrlen));
  475. return sch_ai;
  476. }
  477. static void
  478. free_getaddrinfo_handshake(struct getaddrinfo_handshake *handshake)
  479. {
  480. free(handshake->nodename);
  481. free(handshake->servname);
  482. free(handshake);
  483. }
  484. static s48_ref_t
  485. get_addrinfo_result(s48_call_t call, struct getaddrinfo_handshake *handshake)
  486. {
  487. struct addrinfo *p;
  488. int i, addrinfo_count;
  489. if (handshake->status != 0)
  490. {
  491. int status = handshake->status;
  492. free_getaddrinfo_handshake(handshake);
  493. if (status == EAI_NONAME)
  494. return s48_false_2(call);
  495. else
  496. s48_error_2(call, "s48_getaddrinfo_result", gai_strerror(status), 0);
  497. }
  498. addrinfo_count = 0;
  499. p = handshake->result;
  500. while (p != NULL)
  501. {
  502. ++addrinfo_count;
  503. p = p->ai_next;
  504. }
  505. {
  506. s48_ref_t sch_result = s48_make_vector_2(call, addrinfo_count, s48_unspecific_2(call));
  507. i = 0;
  508. p = handshake->result;
  509. while (i < addrinfo_count)
  510. {
  511. s48_vector_set_2(call, sch_result, i, enter_addrinfo(call, p));
  512. p = p->ai_next;
  513. ++i;
  514. }
  515. freeaddrinfo(handshake->result);
  516. free_getaddrinfo_handshake(handshake);
  517. return sch_result;
  518. }
  519. }
  520. static s48_ref_t
  521. s48_getaddrinfo_result(s48_call_t call, s48_ref_t sch_handshake)
  522. {
  523. return get_addrinfo_result(call, s48_extract_pointer_2(call, sch_handshake));
  524. }
  525. #ifdef HAVE_THREADS
  526. static
  527. DECLARE_THREAD_PROC(getaddrinfo_thread, void_handshake)
  528. {
  529. struct getaddrinfo_handshake *handshake
  530. = (struct getaddrinfo_handshake *) void_handshake;
  531. handshake->status
  532. = getaddrinfo(handshake->nodename, handshake->servname,
  533. &(handshake->hints), &(handshake->result));
  534. s48_note_external_event(handshake->event_uid);
  535. EXIT_THREAD_PROC();
  536. }
  537. #endif
  538. static s48_ref_t
  539. s48_getaddrinfo(s48_call_t call,
  540. s48_ref_t sch_event_uid,
  541. s48_ref_t sch_nodename, s48_ref_t sch_servname,
  542. s48_ref_t sch_hint_flags, s48_ref_t sch_hint_family,
  543. s48_ref_t sch_hint_socktype, s48_ref_t sch_hint_protocol)
  544. {
  545. struct getaddrinfo_handshake *handshake;
  546. #ifdef HAVE_THREADS
  547. thread_type t;
  548. #endif
  549. handshake = malloc(sizeof(struct getaddrinfo_handshake));
  550. if (handshake == NULL)
  551. s48_out_of_memory_error_2(call);
  552. if (s48_false_p_2(call, sch_nodename))
  553. handshake->nodename = NULL;
  554. else
  555. {
  556. handshake->nodename
  557. = maybe_extract_fresh_latin1_string(call, sch_nodename, NI_MAXHOST);
  558. if (handshake->nodename == NULL)
  559. return s48_false_2(call); /* debatable */
  560. }
  561. if (s48_false_p_2(call, sch_servname))
  562. handshake->servname = NULL;
  563. else
  564. {
  565. handshake->servname
  566. = maybe_extract_fresh_latin1_string(call, sch_servname, NI_MAXSERV);
  567. if (handshake->servname == NULL)
  568. return s48_false_2(call); /* debatable */
  569. }
  570. handshake->hints.ai_flags = extract_ai_flags(call, sch_hint_flags);
  571. handshake->hints.ai_family = s48_extract_af(call, sch_hint_family);
  572. handshake->hints.ai_socktype
  573. = (s48_false_p_2(call, sch_hint_socktype)
  574. ? 0
  575. : s48_extract_socket_type(call, sch_hint_socktype));
  576. handshake->hints.ai_protocol
  577. = (s48_false_p_2(call, sch_hint_protocol)
  578. ? 0
  579. : extract_ip_protocol(call, sch_hint_protocol));
  580. handshake->hints.ai_addrlen = 0;
  581. handshake->hints.ai_canonname = NULL;
  582. handshake->hints.ai_addr = NULL;
  583. handshake->hints.ai_next = NULL;
  584. handshake->event_uid = s48_extract_long_2(call, sch_event_uid);
  585. #ifdef HAVE_THREADS
  586. if (START_THREAD(t, getaddrinfo_thread, handshake))
  587. #endif
  588. {
  589. handshake->status
  590. = getaddrinfo(handshake->nodename, handshake->servname,
  591. &(handshake->hints), &(handshake->result));
  592. return get_addrinfo_result(call, handshake);
  593. }
  594. #ifdef HAVE_THREADS
  595. else
  596. {
  597. DETACH_THREAD(t);
  598. return s48_enter_pointer_2(call, handshake);
  599. }
  600. #endif
  601. }
  602. static int
  603. extract_ni_flags(s48_call_t call, s48_ref_t sch_flags)
  604. {
  605. long flags = s48_extract_long_2(call, sch_flags);
  606. return (((flags & 0x01) ? NI_NOFQDN : 0)
  607. | ((flags & 0x02) ? NI_NUMERICHOST : 0)
  608. | ((flags & 0x04) ? NI_NAMEREQD : 0)
  609. | ((flags & 0x08) ? NI_NUMERICSERV : 0)
  610. | ((flags & 0x10) ? NI_DGRAM: 0));
  611. }
  612. static s48_ref_t
  613. enter_ni_flags(s48_call_t call, int flags)
  614. {
  615. return
  616. s48_enter_long_as_fixnum_2(call,
  617. ((flags & NI_NOFQDN) ? 0x01 : 0)
  618. | ((flags & NI_NUMERICHOST) ? 0x02 : 0)
  619. | ((flags & NI_NAMEREQD) ? 0x04 : 0)
  620. | ((flags & NI_NUMERICSERV) ? 0x08 : 0)
  621. | ((flags & NI_DGRAM) ? 0x10 : 0));
  622. }
  623. struct getnameinfo_handshake
  624. {
  625. long event_uid;
  626. struct sockaddr_storage addr;
  627. socklen_t len;
  628. int flags;
  629. int status;
  630. char host[NI_MAXHOST];
  631. char serv[NI_MAXSERV];
  632. };
  633. static s48_ref_t
  634. getnameinfo_result(s48_call_t call, struct getnameinfo_handshake* handshake)
  635. {
  636. s48_ref_t sch_result;
  637. if (handshake->status != 0)
  638. {
  639. int status = handshake->status;
  640. free(handshake);
  641. s48_error_2(call, "s48_getnameinfo_result", gai_strerror(status), 0);
  642. }
  643. /* we use a vector to be able to distinguish from a pair */
  644. sch_result = s48_make_vector_2(call, 2, s48_unspecific_2(call));
  645. s48_vector_set_2(call, sch_result, 0, s48_enter_string_latin_1_2(call, handshake->host));
  646. s48_vector_set_2(call, sch_result, 1, s48_enter_string_latin_1_2(call, handshake->serv));
  647. free(handshake);
  648. return sch_result;
  649. }
  650. static s48_ref_t
  651. s48_getnameinfo_result(s48_call_t call, s48_ref_t sch_handshake)
  652. {
  653. return getnameinfo_result(call, s48_extract_pointer_2(call, sch_handshake));
  654. }
  655. #ifdef HAVE_THREADS
  656. static
  657. DECLARE_THREAD_PROC(getnameinfo_thread, void_handshake)
  658. {
  659. struct getnameinfo_handshake *handshake = void_handshake;
  660. handshake->status
  661. = getnameinfo((struct sockaddr*)&(handshake->addr), handshake->len,
  662. handshake->host, NI_MAXHOST,
  663. handshake->serv, NI_MAXSERV,
  664. handshake->flags);
  665. s48_note_external_event(handshake->event_uid);
  666. EXIT_THREAD_PROC();
  667. }
  668. #endif
  669. static s48_ref_t
  670. s48_getnameinfo(s48_call_t call, s48_ref_t sch_event_uid, s48_ref_t sch_saddr, s48_ref_t sch_flags)
  671. {
  672. const struct sockaddr *sa
  673. = s48_extract_value_pointer_2(call, sch_saddr, const struct sockaddr);
  674. socklen_t salen = s48_value_size_2(call, sch_saddr);
  675. #ifdef HAVE_THREADS
  676. thread_type t;
  677. #endif
  678. struct getnameinfo_handshake *handshake
  679. = malloc(sizeof(struct getnameinfo_handshake));
  680. if (handshake == NULL)
  681. s48_out_of_memory_error_2(call);
  682. memcpy(&(handshake->addr), sa, salen);
  683. handshake->len = salen;
  684. handshake->flags = extract_ni_flags(call, sch_flags);
  685. handshake->event_uid = s48_extract_long_2(call, sch_event_uid);
  686. #ifdef HAVE_THREADS
  687. if (START_THREAD(t, getnameinfo_thread, handshake))
  688. #endif
  689. {
  690. handshake->status
  691. = getnameinfo((struct sockaddr*) &(handshake->addr), handshake->len,
  692. handshake->host, NI_MAXHOST,
  693. handshake->serv, NI_MAXSERV,
  694. handshake->flags);
  695. return getnameinfo_result(call, handshake);
  696. }
  697. #ifdef HAVE_THREADS
  698. else
  699. {
  700. DETACH_THREAD(t);
  701. return s48_enter_pointer_2(call, handshake);
  702. }
  703. #endif
  704. }
  705. /* Adress conversion */
  706. s48_ref_t
  707. s48_inet_pton(s48_call_t call, s48_ref_t sch_af, s48_ref_t sch_src)
  708. {
  709. sa_family_t af = s48_extract_af(call, sch_af);
  710. #ifndef _WIN32
  711. int status;
  712. #endif
  713. switch (af)
  714. {
  715. case AF_INET:
  716. {
  717. char src[INET_ADDRSTRLEN+1]; /* be safe */
  718. struct in_addr addr;
  719. s48_copy_string_to_latin_1_2(call, sch_src, src);
  720. src[s48_string_length_2(call, sch_src)] = '\0';
  721. #ifdef _WIN32
  722. {
  723. INT size = sizeof(struct in_addr);
  724. if (WSAStringToAddress(src, AF_INET, 0,
  725. (LPSOCKADDR)&addr, &size)
  726. == 0)
  727. return enter_in_addr(call, &addr);
  728. }
  729. #else
  730. status = inet_pton(AF_INET, src, &addr);
  731. if (status == 1)
  732. return enter_in_addr(call, &addr);
  733. #endif
  734. break;
  735. }
  736. case AF_INET6:
  737. {
  738. char src[INET6_ADDRSTRLEN+1]; /* be safe */
  739. struct in6_addr addr;
  740. s48_copy_string_to_latin_1_2(call, sch_src, src);
  741. src[s48_string_length_2(call, sch_src)] = '\0';
  742. #ifdef _WIN32
  743. {
  744. INT size = sizeof(struct in6_addr);
  745. if (WSAStringToAddress(src, AF_INET6, 0,
  746. (LPSOCKADDR)&addr, &size)
  747. == 0)
  748. return s48_enter_in6_addr(call, &addr);
  749. }
  750. #else
  751. status = inet_pton(AF_INET6, src, &addr);
  752. if (status == 1)
  753. return s48_enter_in6_addr(call, &addr);
  754. #endif
  755. }
  756. default:
  757. s48_assertion_violation_2(call, "s48_inet_pton", "invalid adddress family", 1, sch_af);
  758. }
  759. return s48_false_2(call);
  760. }
  761. static s48_ref_t
  762. s48_inet_ntop(s48_call_t call, s48_ref_t sch_af, s48_ref_t sch_src)
  763. {
  764. sa_family_t af = s48_extract_af(call, sch_af);
  765. switch (af)
  766. {
  767. case AF_INET:
  768. {
  769. char dest[INET_ADDRSTRLEN+1]; /* be safe */
  770. struct in_addr addr;
  771. extract_in_addr(call, sch_src, &addr);
  772. #ifdef _WIN32
  773. {
  774. DWORD destlen;
  775. if (WSAAddressToString((struct sockaddr *)&addr, sizeof(struct in_addr),
  776. NULL, dest, &destlen) != 0)
  777. s48_os_error_2(call, "s48_inet_ntop", WSAGetLastError(), 2, sch_af, sch_src);
  778. }
  779. #else
  780. if (inet_ntop(AF_INET, &addr, dest, sizeof(dest)) == NULL)
  781. s48_os_error_2(call, "s48_inet_ntop", errno, 2, sch_af, sch_src);
  782. #endif
  783. return s48_enter_string_latin_1_2(call, dest);
  784. }
  785. case AF_INET6:
  786. {
  787. char dest[INET6_ADDRSTRLEN+1]; /* be safe */
  788. struct in6_addr addr;
  789. s48_extract_in6_addr(call, sch_src, &addr);
  790. #ifdef _WIN32
  791. {
  792. DWORD destlen;
  793. if (WSAAddressToString((struct sockaddr *)&addr, sizeof(struct in6_addr),
  794. NULL, dest, &destlen) != 0)
  795. s48_os_error_2(call, "s48_inet_ntop", WSAGetLastError(), 2, sch_af, sch_src);
  796. }
  797. #else
  798. if (inet_ntop(AF_INET6, &addr, dest, sizeof(dest)) == NULL)
  799. s48_os_error_2(call, "s48_inet_ntop", errno, 2, sch_af, sch_src);
  800. #endif
  801. return s48_enter_string_latin_1_2(call, dest);
  802. }
  803. default:
  804. s48_assertion_violation_2(call, "s48_inet_ntop", "invalid adddress family", 1, sch_af);
  805. }
  806. }
  807. /* Address testing */
  808. #define DEFINE_ADDRESS_TESTER(name) \
  809. static s48_ref_t \
  810. s48_##name(s48_call_t call, s48_ref_t sch_addr) \
  811. { \
  812. struct in6_addr addr; \
  813. s48_extract_in6_addr(call, sch_addr, &addr); \
  814. return s48_enter_boolean_2(call, name(&addr)); \
  815. }
  816. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_UNSPECIFIED)
  817. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_LOOPBACK)
  818. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_MULTICAST)
  819. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_LINKLOCAL)
  820. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_SITELOCAL)
  821. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_V4MAPPED)
  822. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_V4COMPAT)
  823. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_MC_NODELOCAL)
  824. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_MC_LINKLOCAL)
  825. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_MC_SITELOCAL)
  826. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_MC_ORGLOCAL)
  827. DEFINE_ADDRESS_TESTER(IN6_IS_ADDR_MC_GLOBAL)
  828. void
  829. s48_init_net_addresses(void)
  830. {
  831. S48_EXPORT_FUNCTION(s48_make_sockaddr_in_raw);
  832. S48_EXPORT_FUNCTION(s48_get_inaddr_any);
  833. S48_EXPORT_FUNCTION(s48_get_inaddr_broadcast);
  834. S48_EXPORT_FUNCTION(s48_make_sockaddr_in6_raw);
  835. S48_EXPORT_FUNCTION(s48_get_in6addr_any);
  836. S48_EXPORT_FUNCTION(s48_get_in6addr_loopback);
  837. #ifndef _WIN32
  838. S48_EXPORT_FUNCTION(s48_make_sockaddr_un_raw);
  839. S48_EXPORT_FUNCTION(s48_if_nametoindex);
  840. S48_EXPORT_FUNCTION(s48_if_indextoname);
  841. S48_EXPORT_FUNCTION(s48_if_nameindex);
  842. #endif
  843. S48_EXPORT_FUNCTION(s48_getaddrinfo);
  844. S48_EXPORT_FUNCTION(s48_getaddrinfo_result);
  845. S48_EXPORT_FUNCTION(s48_getnameinfo);
  846. S48_EXPORT_FUNCTION(s48_getnameinfo_result);
  847. S48_EXPORT_FUNCTION(s48_inet_pton);
  848. S48_EXPORT_FUNCTION(s48_inet_ntop);
  849. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_UNSPECIFIED);
  850. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_LOOPBACK);
  851. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_MULTICAST);
  852. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_LINKLOCAL);
  853. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_SITELOCAL);
  854. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_V4MAPPED);
  855. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_V4COMPAT);
  856. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_MC_NODELOCAL);
  857. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_MC_LINKLOCAL);
  858. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_MC_SITELOCAL);
  859. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_MC_ORGLOCAL);
  860. S48_EXPORT_FUNCTION(s48_IN6_IS_ADDR_MC_GLOBAL);
  861. }