PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/ext/socket/extconf.rb

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