PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/platform/shared/ruby/ext/socket/extconf.rb

http://github.com/rhomobile/rhodes
Ruby | 676 lines | 612 code | 32 blank | 32 comment | 76 complexity | fc2a4c0b5af4e2d924be29582ae079e7 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, MIT, Apache-2.0, LGPL-2.1, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. # frozen_string_literal: false
  2. require 'mkmf'
  3. AF_INET6_SOCKET_CREATION_TEST = <<EOF
  4. #include <sys/types.h>
  5. #ifndef _WIN32
  6. #include <sys/socket.h>
  7. #endif
  8. int
  9. main(void)
  10. {
  11. socket(AF_INET6, SOCK_STREAM, 0);
  12. return 0;
  13. }
  14. EOF
  15. GETADDRINFO_GETNAMEINFO_TEST = <<EOF
  16. #include <stdlib.h>
  17. #ifndef EXIT_SUCCESS
  18. #define EXIT_SUCCESS 0
  19. #endif
  20. #ifndef EXIT_FAILURE
  21. #define EXIT_FAILURE 1
  22. #endif
  23. #ifndef AF_LOCAL
  24. #define AF_LOCAL AF_UNIX
  25. #endif
  26. int
  27. main(void)
  28. {
  29. int passive, gaierr, inet4 = 0, inet6 = 0;
  30. struct addrinfo hints, *ai, *aitop;
  31. char straddr[INET6_ADDRSTRLEN], strport[16];
  32. #ifdef _WIN32
  33. WSADATA retdata;
  34. WSAStartup(MAKEWORD(2, 0), &retdata);
  35. #endif
  36. for (passive = 0; passive <= 1; passive++) {
  37. memset(&hints, 0, sizeof(hints));
  38. hints.ai_family = AF_UNSPEC;
  39. hints.ai_protocol = IPPROTO_TCP;
  40. hints.ai_flags = passive ? AI_PASSIVE : 0;
  41. hints.ai_socktype = SOCK_STREAM;
  42. if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
  43. (void)gai_strerror(gaierr);
  44. goto bad;
  45. }
  46. for (ai = aitop; ai; ai = ai->ai_next) {
  47. if (ai->ai_family == AF_LOCAL) continue;
  48. if (ai->ai_addr == NULL)
  49. goto bad;
  50. #if defined(_AIX)
  51. if (ai->ai_family == AF_INET6 && passive) {
  52. inet6++;
  53. continue;
  54. }
  55. ai->ai_addr->sa_len = ai->ai_addrlen;
  56. ai->ai_addr->sa_family = ai->ai_family;
  57. #endif
  58. if (ai->ai_addrlen == 0 ||
  59. getnameinfo(ai->ai_addr, ai->ai_addrlen,
  60. straddr, sizeof(straddr), strport, sizeof(strport),
  61. NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
  62. goto bad;
  63. }
  64. if (strcmp(strport, "54321") != 0) {
  65. goto bad;
  66. }
  67. switch (ai->ai_family) {
  68. case AF_INET:
  69. if (passive) {
  70. if (strcmp(straddr, "0.0.0.0") != 0) {
  71. goto bad;
  72. }
  73. } else {
  74. if (strcmp(straddr, "127.0.0.1") != 0) {
  75. goto bad;
  76. }
  77. }
  78. inet4++;
  79. break;
  80. case AF_INET6:
  81. if (passive) {
  82. if (strcmp(straddr, "::") != 0) {
  83. goto bad;
  84. }
  85. } else {
  86. if (strcmp(straddr, "::1") != 0) {
  87. goto bad;
  88. }
  89. }
  90. inet6++;
  91. break;
  92. case AF_UNSPEC:
  93. goto bad;
  94. break;
  95. default:
  96. /* another family support? */
  97. break;
  98. }
  99. }
  100. }
  101. if (!(inet4 == 0 || inet4 == 2))
  102. goto bad;
  103. if (!(inet6 == 0 || inet6 == 2))
  104. goto bad;
  105. if (aitop)
  106. freeaddrinfo(aitop);
  107. return EXIT_SUCCESS;
  108. bad:
  109. if (aitop)
  110. freeaddrinfo(aitop);
  111. return EXIT_FAILURE;
  112. }
  113. EOF
  114. RECVMSG_WITH_MSG_PEEK_ALLOCATE_FD_TEST = <<'EOF'
  115. #include <stdlib.h>
  116. #include <stdio.h>
  117. #include <string.h>
  118. #include <sys/types.h>
  119. #include <sys/stat.h>
  120. #include <sys/socket.h>
  121. #include <sys/un.h>
  122. #include <unistd.h>
  123. int main(int argc, char *argv[])
  124. {
  125. int ps[2], sv[2];
  126. int ret;
  127. ssize_t ss;
  128. int s_fd, r_fd;
  129. struct msghdr s_msg, r_msg;
  130. union {
  131. struct cmsghdr hdr;
  132. char dummy[CMSG_SPACE(sizeof(int))];
  133. } s_cmsg, r_cmsg;
  134. struct iovec s_iov, r_iov;
  135. char s_buf[1], r_buf[1];
  136. struct stat s_statbuf, r_statbuf;
  137. ret = pipe(ps);
  138. if (ret == -1) { perror("pipe"); exit(EXIT_FAILURE); }
  139. s_fd = ps[0];
  140. ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, sv);
  141. if (ret == -1) { perror("socketpair"); exit(EXIT_FAILURE); }
  142. s_msg.msg_name = NULL;
  143. s_msg.msg_namelen = 0;
  144. s_msg.msg_iov = &s_iov;
  145. s_msg.msg_iovlen = 1;
  146. s_msg.msg_control = &s_cmsg;
  147. s_msg.msg_controllen = CMSG_SPACE(sizeof(int));;
  148. s_msg.msg_flags = 0;
  149. s_iov.iov_base = &s_buf;
  150. s_iov.iov_len = sizeof(s_buf);
  151. s_buf[0] = 'a';
  152. s_cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(int));
  153. s_cmsg.hdr.cmsg_level = SOL_SOCKET;
  154. s_cmsg.hdr.cmsg_type = SCM_RIGHTS;
  155. memcpy(CMSG_DATA(&s_cmsg.hdr), (char *)&s_fd, sizeof(int));
  156. ss = sendmsg(sv[0], &s_msg, 0);
  157. if (ss == -1) { perror("sendmsg"); exit(EXIT_FAILURE); }
  158. r_msg.msg_name = NULL;
  159. r_msg.msg_namelen = 0;
  160. r_msg.msg_iov = &r_iov;
  161. r_msg.msg_iovlen = 1;
  162. r_msg.msg_control = &r_cmsg;
  163. r_msg.msg_controllen = CMSG_SPACE(sizeof(int));
  164. r_msg.msg_flags = 0;
  165. r_iov.iov_base = &r_buf;
  166. r_iov.iov_len = sizeof(r_buf);
  167. r_buf[0] = '0';
  168. memset(&r_cmsg, 0xff, CMSG_SPACE(sizeof(int)));
  169. ss = recvmsg(sv[1], &r_msg, MSG_PEEK);
  170. if (ss == -1) { perror("recvmsg"); exit(EXIT_FAILURE); }
  171. if (ss != 1) {
  172. fprintf(stderr, "unexpected return value from recvmsg: %ld\n", (long)ss);
  173. exit(EXIT_FAILURE);
  174. }
  175. if (r_buf[0] != 'a') {
  176. fprintf(stderr, "unexpected return data from recvmsg: 0x%02x\n", r_buf[0]);
  177. exit(EXIT_FAILURE);
  178. }
  179. if (r_msg.msg_controllen < CMSG_LEN(sizeof(int))) {
  180. fprintf(stderr, "unexpected: r_msg.msg_controllen < CMSG_LEN(sizeof(int)) not hold: %ld\n",
  181. (long)r_msg.msg_controllen);
  182. exit(EXIT_FAILURE);
  183. }
  184. if (r_cmsg.hdr.cmsg_len < CMSG_LEN(sizeof(int))) {
  185. fprintf(stderr, "unexpected: r_cmsg.hdr.cmsg_len < CMSG_LEN(sizeof(int)) not hold: %ld\n",
  186. (long)r_cmsg.hdr.cmsg_len);
  187. exit(EXIT_FAILURE);
  188. }
  189. memcpy((char *)&r_fd, CMSG_DATA(&r_cmsg.hdr), sizeof(int));
  190. if (r_fd < 0) {
  191. fprintf(stderr, "negative r_fd: %d\n", r_fd);
  192. exit(EXIT_FAILURE);
  193. }
  194. if (r_fd == s_fd) {
  195. fprintf(stderr, "r_fd and s_fd is same: %d\n", r_fd);
  196. exit(EXIT_FAILURE);
  197. }
  198. ret = fstat(s_fd, &s_statbuf);
  199. if (ret == -1) { perror("fstat(s_fd)"); exit(EXIT_FAILURE); }
  200. ret = fstat(r_fd, &r_statbuf);
  201. if (ret == -1) { perror("fstat(r_fd)"); exit(EXIT_FAILURE); }
  202. if (s_statbuf.st_dev != r_statbuf.st_dev ||
  203. s_statbuf.st_ino != r_statbuf.st_ino) {
  204. fprintf(stderr, "dev/ino doesn't match: s_fd:%ld/%ld r_fd:%ld/%ld\n",
  205. (long)s_statbuf.st_dev, (long)s_statbuf.st_ino,
  206. (long)r_statbuf.st_dev, (long)r_statbuf.st_ino);
  207. exit(EXIT_FAILURE);
  208. }
  209. return EXIT_SUCCESS;
  210. }
  211. EOF
  212. def test_recvmsg_with_msg_peek_creates_fds(headers)
  213. case RUBY_PLATFORM
  214. when /linux/
  215. # Linux 2.6.38 allocate fds by recvmsg with MSG_PEEK.
  216. close_fds = true
  217. when /bsd|darwin/
  218. # FreeBSD 8.2.0, NetBSD 5 and MacOS X Snow Leopard doesn't
  219. # allocate fds by recvmsg with MSG_PEEK.
  220. # [ruby-dev:44189]
  221. # http://bugs.ruby-lang.org/issues/5075
  222. close_fds = false
  223. when /cygwin/
  224. # Cygwin doesn't support fd passing.
  225. # http://cygwin.com/ml/cygwin/2003-09/msg01808.html
  226. close_fds = false
  227. else
  228. close_fds = nil
  229. end
  230. if !CROSS_COMPILING
  231. if checking_for("recvmsg() with MSG_PEEK allocate file descriptors") {
  232. try_run(cpp_include(headers) + RECVMSG_WITH_MSG_PEEK_ALLOCATE_FD_TEST)
  233. }
  234. if close_fds == false
  235. warn "unexpected fd-passing recvmsg() with MSG_PEEK behavor on #{RUBY_PLATFORM}: fd allocation unexpected."
  236. elsif close_fds == nil
  237. puts "info: #{RUBY_PLATFORM} recvmsg() with MSG_PEEK allocates fds on fd-passing."
  238. end
  239. close_fds = true
  240. else
  241. if close_fds == true
  242. warn "unexpected fd-passing recvmsg() with MSG_PEEK behavor on #{RUBY_PLATFORM}: fd allocation expected."
  243. elsif close_fds == nil
  244. puts "info: #{RUBY_PLATFORM}: recvmsg() with MSG_PEEK doesn't allocates fds on fd-passing."
  245. end
  246. close_fds = false
  247. end
  248. end
  249. if close_fds == nil
  250. abort <<EOS
  251. Fatal: cannot test fd-passing recvmsg() with MSG_PEEK behavor
  252. because cross-compilation for #{RUBY_PLATFORM}.
  253. If recvmsg() with MSG_PEEK allocates fds on fd passing:
  254. --enable-close-fds-by-recvmsg-with-peek
  255. If recvmsg() with MSG_PEEK doesn't allocate fds on fd passing:
  256. --disable-close-fds-by-recvmsg-with-peek
  257. EOS
  258. end
  259. close_fds
  260. end
  261. $INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
  262. if /darwin/ =~ RUBY_PLATFORM
  263. # For IPv6 extension header access on OS X 10.7+ [Bug #8517]
  264. $CFLAGS << " -D__APPLE_USE_RFC_3542"
  265. end
  266. headers = []
  267. unless $mswin or $mingw
  268. headers = %w<sys/types.h netdb.h string.h sys/socket.h netinet/in.h>
  269. end
  270. %w[
  271. sys/uio.h
  272. xti.h
  273. netinet/in_systm.h
  274. netinet/tcp.h
  275. netinet/tcp_fsm.h
  276. netinet/udp.h
  277. arpa/inet.h
  278. netpacket/packet.h
  279. net/ethernet.h
  280. sys/un.h
  281. ifaddrs.h
  282. sys/ioctl.h
  283. sys/sockio.h
  284. net/if.h
  285. sys/param.h
  286. sys/ucred.h
  287. ucred.h
  288. net/if_dl.h
  289. arpa/nameser.h
  290. resolv.h
  291. ].each {|h|
  292. if have_header(h, headers)
  293. headers << h
  294. end
  295. }
  296. have_struct_member("struct sockaddr", "sa_len", headers) # 4.4BSD
  297. have_struct_member("struct sockaddr_in", "sin_len", headers) # 4.4BSD
  298. have_struct_member("struct sockaddr_in6", "sin6_len", headers) # 4.4BSD
  299. if have_type("struct sockaddr_un", headers) # POSIX
  300. have_struct_member("struct sockaddr_un", "sun_len", headers) # 4.4BSD
  301. end
  302. have_type("struct sockaddr_dl", headers) # AF_LINK address. 4.4BSD since Net2
  303. have_type("struct sockaddr_storage", headers)
  304. have_type("struct addrinfo", headers)
  305. if have_type("socklen_t", headers)
  306. if try_static_assert("sizeof(socklen_t) >= sizeof(long)", headers)
  307. $defs << "-DRSTRING_SOCKLEN=(socklen_t)RSTRING_LEN"
  308. end
  309. end
  310. have_type("struct in_pktinfo", headers) {|src|
  311. src.sub(%r'^/\*top\*/', '\&'"\n#if defined(IPPROTO_IP) && defined(IP_PKTINFO)") <<
  312. "#else\n" << "#error\n" << ">>>>>> no in_pktinfo <<<<<<\n" << "#endif\n"
  313. } and have_struct_member("struct in_pktinfo", "ipi_spec_dst", headers)
  314. have_type("struct in6_pktinfo", headers) {|src|
  315. src.sub(%r'^/\*top\*/', '\&'"\n#if defined(IPPROTO_IPV6) && defined(IPV6_PKTINFO)") <<
  316. "#else\n" << "#error\n" << ">>>>>> no in6_pktinfo <<<<<<\n" << "#endif\n"
  317. }
  318. have_type("struct sockcred", headers)
  319. have_type("struct cmsgcred", headers)
  320. have_type("struct ip_mreq", headers) # 4.4BSD
  321. have_type("struct ip_mreqn", headers) # Linux 2.4
  322. have_type("struct ipv6_mreq", headers) # RFC 3493
  323. have_msg_control = nil
  324. have_msg_control = have_struct_member('struct msghdr', 'msg_control', headers) unless $mswin or $mingw
  325. have_struct_member('struct msghdr', 'msg_accrights', headers)
  326. if have_type("struct tcp_info", headers)
  327. have_const("TCP_ESTABLISHED", headers)
  328. have_const("TCP_SYN_SENT", headers)
  329. have_const("TCP_SYN_RECV", headers)
  330. have_const("TCP_FIN_WAIT1", headers)
  331. have_const("TCP_FIN_WAIT2", headers)
  332. have_const("TCP_TIME_WAIT", headers)
  333. have_const("TCP_CLOSE", headers)
  334. have_const("TCP_CLOSE_WAIT", headers)
  335. have_const("TCP_LAST_ACK", headers)
  336. have_const("TCP_LISTEN", headers)
  337. have_const("TCP_CLOSING", headers)
  338. have_struct_member('struct tcp_info', 'tcpi_state', headers)
  339. if /solaris/ !~ RUBY_PLATFORM
  340. have_struct_member('struct tcp_info', 'tcpi_ca_state', headers)
  341. end
  342. have_struct_member('struct tcp_info', 'tcpi_retransmits', headers)
  343. have_struct_member('struct tcp_info', 'tcpi_probes', headers)
  344. have_struct_member('struct tcp_info', 'tcpi_backoff', headers)
  345. have_struct_member('struct tcp_info', 'tcpi_options', headers)
  346. have_struct_member('struct tcp_info', 'tcpi_snd_wscale', headers)
  347. have_struct_member('struct tcp_info', 'tcpi_rcv_wscale', headers)
  348. have_struct_member('struct tcp_info', 'tcpi_rto', headers)
  349. have_struct_member('struct tcp_info', 'tcpi_ato', headers)
  350. have_struct_member('struct tcp_info', 'tcpi_snd_mss', headers)
  351. have_struct_member('struct tcp_info', 'tcpi_rcv_mss', headers)
  352. have_struct_member('struct tcp_info', 'tcpi_unacked', headers)
  353. have_struct_member('struct tcp_info', 'tcpi_sacked', headers)
  354. have_struct_member('struct tcp_info', 'tcpi_lost', headers)
  355. have_struct_member('struct tcp_info', 'tcpi_retrans', headers)
  356. have_struct_member('struct tcp_info', 'tcpi_fackets', headers)
  357. have_struct_member('struct tcp_info', 'tcpi_last_data_sent', headers)
  358. have_struct_member('struct tcp_info', 'tcpi_last_ack_sent', headers)
  359. have_struct_member('struct tcp_info', 'tcpi_last_data_recv', headers)
  360. have_struct_member('struct tcp_info', 'tcpi_last_ack_recv', headers)
  361. have_struct_member('struct tcp_info', 'tcpi_pmtu', headers)
  362. have_struct_member('struct tcp_info', 'tcpi_rcv_ssthresh', headers)
  363. have_struct_member('struct tcp_info', 'tcpi_rtt', headers)
  364. have_struct_member('struct tcp_info', 'tcpi_rttvar', headers)
  365. have_struct_member('struct tcp_info', 'tcpi_snd_ssthresh', headers)
  366. have_struct_member('struct tcp_info', 'tcpi_snd_cwnd', headers)
  367. have_struct_member('struct tcp_info', 'tcpi_advmss', headers)
  368. have_struct_member('struct tcp_info', 'tcpi_reordering', headers)
  369. have_struct_member('struct tcp_info', 'tcpi_rcv_rtt', headers)
  370. have_struct_member('struct tcp_info', 'tcpi_rcv_space', headers)
  371. have_struct_member('struct tcp_info', 'tcpi_total_retrans', headers)
  372. # FreeBSD extension
  373. have_struct_member('struct tcp_info', 'tcpi_snd_wnd', headers)
  374. have_struct_member('struct tcp_info', 'tcpi_snd_bwnd', headers)
  375. have_struct_member('struct tcp_info', 'tcpi_snd_nxt', headers)
  376. have_struct_member('struct tcp_info', 'tcpi_rcv_nxt', headers)
  377. have_struct_member('struct tcp_info', 'tcpi_toe_tid', headers)
  378. have_struct_member('struct tcp_info', 'tcpi_snd_rexmitpack', headers)
  379. have_struct_member('struct tcp_info', 'tcpi_rcv_ooopack', headers)
  380. have_struct_member('struct tcp_info', 'tcpi_snd_zerowin', headers)
  381. end
  382. case RUBY_PLATFORM
  383. when /mswin(32|64)|mingw/
  384. test_func = "WSACleanup"
  385. have_library("ws2_32", "WSACleanup", headers)
  386. when /cygwin/
  387. test_func = "socket(0,0,0)"
  388. when /haiku/
  389. test_func = "socket(0,0,0)"
  390. have_library("network", "socket(0,0,0)", headers)
  391. else
  392. test_func = "socket(0,0,0)"
  393. have_library("nsl", 't_open("", 0, (struct t_info *)NULL)', headers) # SunOS
  394. have_library("socket", "socket(0,0,0)", headers) # SunOS
  395. end
  396. if have_func(test_func, headers)
  397. have_func("sendmsg(0, (struct msghdr *)NULL, 0)", headers) # POSIX
  398. have_recvmsg = have_func("recvmsg(0, (struct msghdr *)NULL, 0)", headers) # POSIX
  399. have_func("freehostent((struct hostent *)NULL)", headers) # RFC 2553
  400. have_func("freeaddrinfo((struct addrinfo *)NULL)", headers) # RFC 2553
  401. if /haiku/ !~ RUBY_PLATFORM and
  402. have_func("gai_strerror(0)", headers) # POSIX
  403. if checking_for("gai_strerror() returns const pointer") {!try_compile(<<EOF)}
  404. #{cpp_include(headers)}
  405. #include <stdlib.h>
  406. void
  407. conftest_gai_strerror_is_const()
  408. {
  409. *gai_strerror(0) = 0;
  410. }
  411. EOF
  412. $defs << "-DGAI_STRERROR_CONST"
  413. end
  414. end
  415. have_func("accept4", headers)
  416. have_func('inet_ntop(0, (const void *)0, (char *)0, 0)', headers) or
  417. have_func("inet_ntoa(*(struct in_addr *)NULL)", headers)
  418. have_func('inet_pton(0, "", (void *)0)', headers) or
  419. have_func('inet_aton("", (struct in_addr *)0)', headers)
  420. have_func('getservbyport(0, "")', headers)
  421. have_func("getifaddrs((struct ifaddrs **)NULL)", headers)
  422. have_func("getpeereid", headers)
  423. have_func("getpeerucred(0, (ucred_t **)NULL)", headers) # SunOS
  424. have_func_decl = proc do |name, headers|
  425. if !checking_for("declaration of #{name}()") {!%w[int void].all? {|ret| try_compile(<<EOF)}}
  426. #{cpp_include(headers)}
  427. #{ret} #{name}(void);
  428. EOF
  429. $defs << "-DNEED_#{name.tr_cpp}_DECL"
  430. end
  431. end
  432. if have_func('if_indextoname(0, "")', headers)
  433. have_func_decl["if_indextoname"]
  434. end
  435. if have_func('if_nametoindex("")', headers)
  436. have_func_decl["if_nametoindex"]
  437. end
  438. have_func("hsterror", headers)
  439. have_func('getipnodebyname("", 0, 0, (int *)0)', headers) # RFC 2553
  440. have_func('gethostbyname2("", 0)', headers) # RFC 2133
  441. have_func("socketpair(0, 0, 0, 0)", headers)
  442. unless have_func("gethostname((char *)0, 0)", headers)
  443. have_func("uname((struct utsname *)NULL)", headers)
  444. end
  445. ipv6 = false
  446. default_ipv6 = /haiku/ !~ RUBY_PLATFORM
  447. if enable_config("ipv6", default_ipv6)
  448. if checking_for("ipv6") {try_link(AF_INET6_SOCKET_CREATION_TEST)}
  449. $defs << "-DENABLE_IPV6" << "-DINET6"
  450. ipv6 = true
  451. end
  452. end
  453. if ipv6
  454. if $mingw
  455. $CPPFLAGS << " -D_WIN32_WINNT=0x501" unless $CPPFLAGS.include?("_WIN32_WINNT")
  456. end
  457. ipv6lib = nil
  458. class << (fmt = "unknown")
  459. def %(s) s || self end
  460. end
  461. idirs, ldirs = dir_config("inet6", %w[/usr/inet6 /usr/local/v6].find {|d| File.directory?(d)})
  462. checking_for("ipv6 type", fmt) do
  463. if have_macro("IPV6_INRIA_VERSION", "netinet/in.h")
  464. "inria"
  465. elsif have_macro("__KAME__", "netinet/in.h")
  466. have_library(ipv6lib = "inet6")
  467. "kame"
  468. elsif have_macro("_TOSHIBA_INET6", "sys/param.h")
  469. have_library(ipv6lib = "inet6") and "toshiba"
  470. elsif have_macro("__V6D__", "sys/v6config.h")
  471. have_library(ipv6lib = "v6") and "v6d"
  472. elsif have_macro("_ZETA_MINAMI_INET6", "sys/param.h")
  473. have_library(ipv6lib = "inet6") and "zeta"
  474. elsif have_library("inet6")
  475. "inet6"
  476. end
  477. end or not ipv6lib or abort <<EOS
  478. Fatal: no #{ipv6lib} library found. cannot continue.
  479. You need to fetch lib#{ipv6lib}.a from appropriate
  480. ipv6 kit and compile beforehand.
  481. EOS
  482. end
  483. if !have_macro("IPPROTO_IPV6", headers) && have_const("IPPROTO_IPV6", headers)
  484. IO.read(File.join(File.dirname(__FILE__), "mkconstants.rb")).sub(/\A.*^__END__$/m, '').split(/\r?\n/).grep(/\AIPPROTO_\w*/){$&}.each {|name|
  485. have_const(name, headers) unless $defs.include?("-DHAVE_CONST_#{name.upcase}")
  486. }
  487. end
  488. if enable_config("close-fds-by-recvmsg-with-peek") {
  489. have_msg_control && have_recvmsg &&
  490. have_const('AF_UNIX', headers) && have_const('SCM_RIGHTS', headers) &&
  491. test_recvmsg_with_msg_peek_creates_fds(headers)
  492. }
  493. $defs << "-DFD_PASSING_WORK_WITH_RECVMSG_MSG_PEEK"
  494. end
  495. case enable_config("wide-getaddrinfo")
  496. when true
  497. getaddr_info_ok = :wide
  498. when nil, false
  499. getaddr_info_ok = (:wide if getaddr_info_ok.nil?)
  500. if have_func("getnameinfo", headers) and have_func("getaddrinfo", headers)
  501. if CROSS_COMPILING ||
  502. checking_for("system getaddrinfo working") {
  503. try_run(cpp_include(headers) + GETADDRINFO_GETNAMEINFO_TEST)
  504. }
  505. getaddr_info_ok = :os
  506. end
  507. end
  508. else
  509. raise "unexpected enable_config() value"
  510. end
  511. if ipv6 and not getaddr_info_ok
  512. abort <<EOS
  513. Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
  514. But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
  515. you cannot compile IPv6 socket classes with broken these functions.
  516. You can try --enable-wide-getaddrinfo.
  517. EOS
  518. end
  519. case with_config("lookup-order-hack", "UNSPEC")
  520. when "INET"
  521. $defs << "-DLOOKUP_ORDER_HACK_INET"
  522. when "INET6"
  523. $defs << "-DLOOKUP_ORDER_HACK_INET6"
  524. when "UNSPEC"
  525. # nothing special
  526. else
  527. abort <<EOS
  528. Fatal: invalid value for --with-lookup-order-hack (expected INET, INET6 or UNSPEC)
  529. EOS
  530. end
  531. $objs = [
  532. "init.#{$OBJEXT}",
  533. "constants.#{$OBJEXT}",
  534. "basicsocket.#{$OBJEXT}",
  535. "socket.#{$OBJEXT}",
  536. "ipsocket.#{$OBJEXT}",
  537. "tcpsocket.#{$OBJEXT}",
  538. "tcpserver.#{$OBJEXT}",
  539. "sockssocket.#{$OBJEXT}",
  540. "udpsocket.#{$OBJEXT}",
  541. "unixsocket.#{$OBJEXT}",
  542. "unixserver.#{$OBJEXT}",
  543. "option.#{$OBJEXT}",
  544. "ancdata.#{$OBJEXT}",
  545. "raddrinfo.#{$OBJEXT}",
  546. "ifaddr.#{$OBJEXT}"
  547. ]
  548. if getaddr_info_ok == :wide
  549. if !have_type("struct in6_addr", headers) and have_type("struct in_addr6", headers)
  550. $defs.pop(2)
  551. $defs << "-Din_addr6=in6_addr"
  552. end
  553. if have_struct_member("struct in6_addr", "s6_addr8", headers)
  554. $defs[-1] = "-Ds6_addr=s6_addr8"
  555. end
  556. if ipv6 == "kame" && have_struct_member("struct in6_addr", "s6_addr32", headers)
  557. $defs[-1] = "-DFAITH"
  558. end
  559. $CPPFLAGS="-I. "+$CPPFLAGS
  560. $objs += ["getaddrinfo.#{$OBJEXT}"]
  561. $objs += ["getnameinfo.#{$OBJEXT}"]
  562. $defs << "-DGETADDRINFO_EMU"
  563. end
  564. # workaround for recent Windows SDK
  565. $defs << "-DIPPROTO_IPV6=IPPROTO_IPV6" if $defs.include?("-DHAVE_CONST_IPPROTO_IPV6") && !have_macro("IPPROTO_IPV6")
  566. $distcleanfiles << "constants.h" << "constdefs.*"
  567. if enable_config("socks", ENV["SOCKS_SERVER"])
  568. if have_library("socks5", "SOCKSinit")
  569. $defs << "-DSOCKS5" << "-DSOCKS"
  570. elsif have_library("socks", "Rconnect")
  571. $defs << "-DSOCKS"
  572. end
  573. end
  574. hdr = "netinet6/in6.h"
  575. if /darwin/ =~ RUBY_PLATFORM and !try_compile(<<"SRC", nil, :werror=>true)
  576. #include <netinet/in.h>
  577. int t(struct in6_addr *addr) {return IN6_IS_ADDR_UNSPECIFIED(addr);}
  578. SRC
  579. print "fixing apple's netinet6/in6.rb ..."; $stdout.flush
  580. in6 = File.read("/usr/include/#{hdr}")
  581. if in6.gsub!(/\*\(const\s+__uint32_t\s+\*\)\(const\s+void\s+\*\)\(&(\(\w+\))->s6_addr\[(\d+)\]\)/) do
  582. i, r = $2.to_i.divmod(4)
  583. if r.zero?
  584. "#$1->__u6_addr.__u6_addr32[#{i}]"
  585. else
  586. $&
  587. end
  588. end
  589. FileUtils.mkdir_p(File.dirname(hdr))
  590. open(hdr, "w") {|f| f.write(in6)}
  591. $distcleanfiles << hdr
  592. $distcleandirs << File.dirname(hdr)
  593. puts "done"
  594. else
  595. puts "not needed"
  596. end
  597. end
  598. create_makefile("socket")
  599. end