00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "rubysocket.h"
00012
00013 static VALUE sock_s_unpack_sockaddr_in(VALUE, VALUE);
00014
00015 void
00016 rsock_sys_fail_host_port(const char *mesg, VALUE host, VALUE port)
00017 {
00018 rsock_syserr_fail_host_port(errno, mesg, host, port);
00019 }
00020
00021 void
00022 rsock_syserr_fail_host_port(int err, const char *mesg, VALUE host, VALUE port)
00023 {
00024 VALUE message;
00025
00026 port = rb_String(port);
00027
00028 message = rb_sprintf("%s for \"%s\" port %s",
00029 mesg, StringValueCStr(host), StringValueCStr(port));
00030
00031 rb_syserr_fail_str(err, message);
00032 }
00033
00034 void
00035 rsock_sys_fail_path(const char *mesg, VALUE path)
00036 {
00037 rsock_syserr_fail_path(errno, mesg, path);
00038 }
00039
00040 void
00041 rsock_syserr_fail_path(int err, const char *mesg, VALUE path)
00042 {
00043 VALUE message;
00044
00045 if (RB_TYPE_P(path, T_STRING)) {
00046 if (memchr(RSTRING_PTR(path), '\0', RSTRING_LEN(path))) {
00047 path = rb_str_inspect(path);
00048 message = rb_sprintf("%s for %s", mesg,
00049 StringValueCStr(path));
00050 }
00051 else {
00052 message = rb_sprintf("%s for \"%s\"", mesg,
00053 StringValueCStr(path));
00054 }
00055 rb_syserr_fail_str(err, message);
00056 }
00057 else {
00058 rb_syserr_fail(err, mesg);
00059 }
00060 }
00061
00062 void
00063 rsock_sys_fail_sockaddr(const char *mesg, struct sockaddr *addr, socklen_t len)
00064 {
00065 rsock_syserr_fail_sockaddr(errno, mesg, addr, len);
00066 }
00067
00068 void
00069 rsock_syserr_fail_sockaddr(int err, const char *mesg, struct sockaddr *addr, socklen_t len)
00070 {
00071 VALUE rai;
00072
00073 rai = rsock_addrinfo_new(addr, len, PF_UNSPEC, 0, 0, Qnil, Qnil);
00074
00075 rsock_syserr_fail_raddrinfo(err, mesg, rai);
00076 }
00077
00078 void
00079 rsock_sys_fail_raddrinfo(const char *mesg, VALUE rai)
00080 {
00081 rsock_syserr_fail_raddrinfo(errno, mesg, rai);
00082 }
00083
00084 void
00085 rsock_syserr_fail_raddrinfo(int err, const char *mesg, VALUE rai)
00086 {
00087 VALUE str, message;
00088
00089 str = rsock_addrinfo_inspect_sockaddr(rai);
00090 message = rb_sprintf("%s for %s", mesg, StringValueCStr(str));
00091
00092 rb_syserr_fail_str(err, message);
00093 }
00094
00095 void
00096 rsock_sys_fail_raddrinfo_or_sockaddr(const char *mesg, VALUE addr, VALUE rai)
00097 {
00098 rsock_syserr_fail_raddrinfo_or_sockaddr(errno, mesg, addr, rai);
00099 }
00100
00101 void
00102 rsock_syserr_fail_raddrinfo_or_sockaddr(int err, const char *mesg, VALUE addr, VALUE rai)
00103 {
00104 if (NIL_P(rai)) {
00105 StringValue(addr);
00106
00107 rsock_syserr_fail_sockaddr(err, mesg,
00108 (struct sockaddr *)RSTRING_PTR(addr),
00109 (socklen_t)RSTRING_LEN(addr));
00110 }
00111 else
00112 rsock_syserr_fail_raddrinfo(err, mesg, rai);
00113 }
00114
00115 static void
00116 setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
00117 {
00118 *dv = rsock_family_arg(domain);
00119 *tv = rsock_socktype_arg(type);
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 static VALUE
00141 sock_initialize(int argc, VALUE *argv, VALUE sock)
00142 {
00143 VALUE domain, type, protocol;
00144 int fd;
00145 int d, t;
00146
00147 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
00148 if (NIL_P(protocol))
00149 protocol = INT2FIX(0);
00150
00151 rb_secure(3);
00152 setup_domain_and_type(domain, &d, type, &t);
00153 fd = rsock_socket(d, t, NUM2INT(protocol));
00154 if (fd < 0) rb_sys_fail("socket(2)");
00155
00156 return rsock_init_sock(sock, fd);
00157 }
00158
00159 #if defined HAVE_SOCKETPAIR
00160 static VALUE
00161 io_call_close(VALUE io)
00162 {
00163 return rb_funcall(io, rb_intern("close"), 0, 0);
00164 }
00165
00166 static VALUE
00167 io_close(VALUE io)
00168 {
00169 return rb_rescue(io_call_close, io, 0, 0);
00170 }
00171
00172 static VALUE
00173 pair_yield(VALUE pair)
00174 {
00175 return rb_ensure(rb_yield, pair, io_close, rb_ary_entry(pair, 1));
00176 }
00177 #endif
00178
00179 #if defined HAVE_SOCKETPAIR
00180
00181 static int
00182 rsock_socketpair0(int domain, int type, int protocol, int sv[2])
00183 {
00184 int ret;
00185
00186 #ifdef SOCK_CLOEXEC
00187 static int try_sock_cloexec = 1;
00188 if (try_sock_cloexec) {
00189 ret = socketpair(domain, type|SOCK_CLOEXEC, protocol, sv);
00190 if (ret == -1 && errno == EINVAL) {
00191
00192 ret = socketpair(domain, type, protocol, sv);
00193 if (ret != -1) {
00194
00195
00196
00197
00198 try_sock_cloexec = 0;
00199 }
00200 }
00201 }
00202 else {
00203 ret = socketpair(domain, type, protocol, sv);
00204 }
00205 #else
00206 ret = socketpair(domain, type, protocol, sv);
00207 #endif
00208
00209 if (ret == -1) {
00210 return -1;
00211 }
00212
00213 rb_fd_fix_cloexec(sv[0]);
00214 rb_fd_fix_cloexec(sv[1]);
00215
00216 return ret;
00217 }
00218
00219 static int
00220 rsock_socketpair(int domain, int type, int protocol, int sv[2])
00221 {
00222 int ret;
00223
00224 ret = rsock_socketpair0(domain, type, protocol, sv);
00225 if (ret < 0 && (errno == EMFILE || errno == ENFILE)) {
00226 rb_gc();
00227 ret = rsock_socketpair0(domain, type, protocol, sv);
00228 }
00229
00230 return ret;
00231 }
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 VALUE
00263 rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
00264 {
00265 VALUE domain, type, protocol;
00266 int d, t, p, sp[2];
00267 int ret;
00268 VALUE s1, s2, r;
00269
00270 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
00271 if (NIL_P(protocol))
00272 protocol = INT2FIX(0);
00273
00274 setup_domain_and_type(domain, &d, type, &t);
00275 p = NUM2INT(protocol);
00276 ret = rsock_socketpair(d, t, p, sp);
00277 if (ret < 0) {
00278 rb_sys_fail("socketpair(2)");
00279 }
00280 rb_fd_fix_cloexec(sp[0]);
00281 rb_fd_fix_cloexec(sp[1]);
00282
00283 s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
00284 s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
00285 r = rb_assoc_new(s1, s2);
00286 if (rb_block_given_p()) {
00287 return rb_ensure(pair_yield, r, io_close, s1);
00288 }
00289 return r;
00290 }
00291 #else
00292 #define rsock_sock_s_socketpair rb_f_notimplement
00293 #endif
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 static VALUE
00407 sock_connect(VALUE sock, VALUE addr)
00408 {
00409 VALUE rai;
00410 rb_io_t *fptr;
00411 int fd, n;
00412
00413 SockAddrStringValueWithAddrinfo(addr, rai);
00414 addr = rb_str_new4(addr);
00415 GetOpenFile(sock, fptr);
00416 fd = fptr->fd;
00417 n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0);
00418 if (n < 0) {
00419 rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
00420 }
00421
00422 return INT2FIX(n);
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 static VALUE
00468 sock_connect_nonblock(VALUE sock, VALUE addr)
00469 {
00470 VALUE rai;
00471 rb_io_t *fptr;
00472 int n;
00473
00474 SockAddrStringValueWithAddrinfo(addr, rai);
00475 addr = rb_str_new4(addr);
00476 GetOpenFile(sock, fptr);
00477 rb_io_set_nonblock(fptr);
00478 n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr));
00479 if (n < 0) {
00480 if (errno == EINPROGRESS)
00481 rb_readwrite_sys_fail(RB_IO_WAIT_WRITABLE, "connect(2) would block");
00482 rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
00483 }
00484
00485 return INT2FIX(n);
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574 static VALUE
00575 sock_bind(VALUE sock, VALUE addr)
00576 {
00577 VALUE rai;
00578 rb_io_t *fptr;
00579
00580 SockAddrStringValueWithAddrinfo(addr, rai);
00581 GetOpenFile(sock, fptr);
00582 if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr)) < 0)
00583 rsock_sys_fail_raddrinfo_or_sockaddr("bind(2)", addr, rai);
00584
00585 return INT2FIX(0);
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 VALUE
00659 rsock_sock_listen(VALUE sock, VALUE log)
00660 {
00661 rb_io_t *fptr;
00662 int backlog;
00663
00664 backlog = NUM2INT(log);
00665 GetOpenFile(sock, fptr);
00666 if (listen(fptr->fd, backlog) < 0)
00667 rb_sys_fail("listen(2)");
00668
00669 return INT2FIX(0);
00670 }
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 static VALUE
00778 sock_recvfrom(int argc, VALUE *argv, VALUE sock)
00779 {
00780 return rsock_s_recvfrom(sock, argc, argv, RECV_SOCKET);
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 static VALUE
00846 sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
00847 {
00848 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
00849 }
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 static VALUE
00866 sock_accept(VALUE sock)
00867 {
00868 rb_io_t *fptr;
00869 VALUE sock2;
00870 union_sockaddr buf;
00871 socklen_t len = (socklen_t)sizeof buf;
00872
00873 GetOpenFile(sock, fptr);
00874 sock2 = rsock_s_accept(rb_cSocket,fptr->fd,&buf.addr,&len);
00875
00876 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len));
00877 }
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 static VALUE
00931 sock_accept_nonblock(VALUE sock)
00932 {
00933 rb_io_t *fptr;
00934 VALUE sock2;
00935 union_sockaddr buf;
00936 socklen_t len = (socklen_t)sizeof buf;
00937
00938 GetOpenFile(sock, fptr);
00939 sock2 = rsock_s_accept_nonblock(rb_cSocket, fptr, &buf.addr, &len);
00940 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len));
00941 }
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 static VALUE
00982 sock_sysaccept(VALUE sock)
00983 {
00984 rb_io_t *fptr;
00985 VALUE sock2;
00986 union_sockaddr buf;
00987 socklen_t len = (socklen_t)sizeof buf;
00988
00989 GetOpenFile(sock, fptr);
00990 sock2 = rsock_s_accept(0,fptr->fd,&buf.addr,&len);
00991
00992 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, &buf.addr, len));
00993 }
00994
00995 #ifdef HAVE_GETHOSTNAME
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007 static VALUE
01008 sock_gethostname(VALUE obj)
01009 {
01010 #ifndef HOST_NAME_MAX
01011 # define HOST_NAME_MAX 1024
01012 #endif
01013 char buf[HOST_NAME_MAX+1];
01014
01015 rb_secure(3);
01016 if (gethostname(buf, (int)sizeof buf - 1) < 0)
01017 rb_sys_fail("gethostname(3)");
01018
01019 buf[sizeof buf - 1] = '\0';
01020 return rb_str_new2(buf);
01021 }
01022 #else
01023 #ifdef HAVE_UNAME
01024
01025 #include <sys/utsname.h>
01026
01027 static VALUE
01028 sock_gethostname(VALUE obj)
01029 {
01030 struct utsname un;
01031
01032 rb_secure(3);
01033 uname(&un);
01034 return rb_str_new2(un.nodename);
01035 }
01036 #else
01037 #define sock_gethostname rb_f_notimplement
01038 #endif
01039 #endif
01040
01041 static VALUE
01042 make_addrinfo(struct rb_addrinfo *res0, int norevlookup)
01043 {
01044 VALUE base, ary;
01045 struct addrinfo *res;
01046
01047 if (res0 == NULL) {
01048 rb_raise(rb_eSocket, "host not found");
01049 }
01050 base = rb_ary_new();
01051 for (res = res0->ai; res; res = res->ai_next) {
01052 ary = rsock_ipaddr(res->ai_addr, res->ai_addrlen, norevlookup);
01053 if (res->ai_canonname) {
01054 RARRAY_PTR(ary)[2] = rb_str_new2(res->ai_canonname);
01055 }
01056 rb_ary_push(ary, INT2FIX(res->ai_family));
01057 rb_ary_push(ary, INT2FIX(res->ai_socktype));
01058 rb_ary_push(ary, INT2FIX(res->ai_protocol));
01059 rb_ary_push(base, ary);
01060 }
01061 return base;
01062 }
01063
01064 static VALUE
01065 sock_sockaddr(struct sockaddr *addr, socklen_t len)
01066 {
01067 char *ptr;
01068
01069 switch (addr->sa_family) {
01070 case AF_INET:
01071 ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
01072 len = (socklen_t)sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
01073 break;
01074 #ifdef AF_INET6
01075 case AF_INET6:
01076 ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
01077 len = (socklen_t)sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
01078 break;
01079 #endif
01080 default:
01081 rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
01082 break;
01083 }
01084 return rb_str_new(ptr, len);
01085 }
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096 static VALUE
01097 sock_s_gethostbyname(VALUE obj, VALUE host)
01098 {
01099 rb_secure(3);
01100 return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
01101 }
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112 static VALUE
01113 sock_s_gethostbyaddr(int argc, VALUE *argv)
01114 {
01115 VALUE addr, family;
01116 struct hostent *h;
01117 char **pch;
01118 VALUE ary, names;
01119 int t = AF_INET;
01120
01121 rb_scan_args(argc, argv, "11", &addr, &family);
01122 StringValue(addr);
01123 if (!NIL_P(family)) {
01124 t = rsock_family_arg(family);
01125 }
01126 #ifdef AF_INET6
01127 else if (RSTRING_LEN(addr) == 16) {
01128 t = AF_INET6;
01129 }
01130 #endif
01131 h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), t);
01132 if (h == NULL) {
01133 #ifdef HAVE_HSTRERROR
01134 extern int h_errno;
01135 rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
01136 #else
01137 rb_raise(rb_eSocket, "host not found");
01138 #endif
01139 }
01140 ary = rb_ary_new();
01141 rb_ary_push(ary, rb_str_new2(h->h_name));
01142 names = rb_ary_new();
01143 rb_ary_push(ary, names);
01144 if (h->h_aliases != NULL) {
01145 for (pch = h->h_aliases; *pch; pch++) {
01146 rb_ary_push(names, rb_str_new2(*pch));
01147 }
01148 }
01149 rb_ary_push(ary, INT2NUM(h->h_addrtype));
01150 #ifdef h_addr
01151 for (pch = h->h_addr_list; *pch; pch++) {
01152 rb_ary_push(ary, rb_str_new(*pch, h->h_length));
01153 }
01154 #else
01155 rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
01156 #endif
01157
01158 return ary;
01159 }
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 static VALUE
01175 sock_s_getservbyname(int argc, VALUE *argv)
01176 {
01177 VALUE service, proto;
01178 struct servent *sp;
01179 long port;
01180 const char *servicename, *protoname = "tcp";
01181
01182 rb_scan_args(argc, argv, "11", &service, &proto);
01183 StringValue(service);
01184 if (!NIL_P(proto)) StringValue(proto);
01185 servicename = StringValueCStr(service);
01186 if (!NIL_P(proto)) protoname = StringValueCStr(proto);
01187 sp = getservbyname(servicename, protoname);
01188 if (sp) {
01189 port = ntohs(sp->s_port);
01190 }
01191 else {
01192 char *end;
01193
01194 port = STRTOUL(servicename, &end, 0);
01195 if (*end != '\0') {
01196 rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
01197 }
01198 }
01199 return INT2FIX(port);
01200 }
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 static VALUE
01216 sock_s_getservbyport(int argc, VALUE *argv)
01217 {
01218 VALUE port, proto;
01219 struct servent *sp;
01220 long portnum;
01221 const char *protoname = "tcp";
01222
01223 rb_scan_args(argc, argv, "11", &port, &proto);
01224 portnum = NUM2LONG(port);
01225 if (portnum != (uint16_t)portnum) {
01226 const char *s = portnum > 0 ? "big" : "small";
01227 rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
01228 }
01229 if (!NIL_P(proto)) protoname = StringValueCStr(proto);
01230
01231 sp = getservbyport((int)htons((uint16_t)portnum), protoname);
01232 if (!sp) {
01233 rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
01234 }
01235 return rb_tainted_str_new2(sp->s_name);
01236 }
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 static VALUE
01271 sock_s_getaddrinfo(int argc, VALUE *argv)
01272 {
01273 VALUE host, port, family, socktype, protocol, flags, ret, revlookup;
01274 struct addrinfo hints;
01275 struct rb_addrinfo *res;
01276 int norevlookup;
01277
01278 rb_scan_args(argc, argv, "25", &host, &port, &family, &socktype, &protocol, &flags, &revlookup);
01279
01280 MEMZERO(&hints, struct addrinfo, 1);
01281 hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
01282
01283 if (!NIL_P(socktype)) {
01284 hints.ai_socktype = rsock_socktype_arg(socktype);
01285 }
01286 if (!NIL_P(protocol)) {
01287 hints.ai_protocol = NUM2INT(protocol);
01288 }
01289 if (!NIL_P(flags)) {
01290 hints.ai_flags = NUM2INT(flags);
01291 }
01292 if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
01293 norevlookup = rsock_do_not_reverse_lookup;
01294 }
01295 res = rsock_getaddrinfo(host, port, &hints, 0);
01296
01297 ret = make_addrinfo(res, norevlookup);
01298 rb_freeaddrinfo(res);
01299 return ret;
01300 }
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324 static VALUE
01325 sock_s_getnameinfo(int argc, VALUE *argv)
01326 {
01327 VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
01328 char *hptr, *pptr;
01329 char hbuf[1024], pbuf[1024];
01330 int fl;
01331 struct rb_addrinfo *res = NULL;
01332 struct addrinfo hints, *r;
01333 int error, saved_errno;
01334 union_sockaddr ss;
01335 struct sockaddr *sap;
01336 socklen_t salen;
01337
01338 sa = flags = Qnil;
01339 rb_scan_args(argc, argv, "11", &sa, &flags);
01340
01341 fl = 0;
01342 if (!NIL_P(flags)) {
01343 fl = NUM2INT(flags);
01344 }
01345 tmp = rb_check_sockaddr_string_type(sa);
01346 if (!NIL_P(tmp)) {
01347 sa = tmp;
01348 if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
01349 rb_raise(rb_eTypeError, "sockaddr length too big");
01350 }
01351 memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
01352 if (!VALIDATE_SOCKLEN(&ss.addr, RSTRING_LEN(sa))) {
01353 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
01354 }
01355 sap = &ss.addr;
01356 salen = RSTRING_SOCKLEN(sa);
01357 goto call_nameinfo;
01358 }
01359 tmp = rb_check_array_type(sa);
01360 if (!NIL_P(tmp)) {
01361 sa = tmp;
01362 MEMZERO(&hints, struct addrinfo, 1);
01363 if (RARRAY_LEN(sa) == 3) {
01364 af = RARRAY_PTR(sa)[0];
01365 port = RARRAY_PTR(sa)[1];
01366 host = RARRAY_PTR(sa)[2];
01367 }
01368 else if (RARRAY_LEN(sa) >= 4) {
01369 af = RARRAY_PTR(sa)[0];
01370 port = RARRAY_PTR(sa)[1];
01371 host = RARRAY_PTR(sa)[3];
01372 if (NIL_P(host)) {
01373 host = RARRAY_PTR(sa)[2];
01374 }
01375 else {
01376
01377
01378
01379
01380 #ifdef AI_NUMERICHOST
01381 hints.ai_flags |= AI_NUMERICHOST;
01382 #endif
01383 }
01384 }
01385 else {
01386 rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
01387 RARRAY_LEN(sa));
01388 }
01389
01390 if (NIL_P(host)) {
01391 hptr = NULL;
01392 }
01393 else {
01394 strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
01395 hbuf[sizeof(hbuf) - 1] = '\0';
01396 hptr = hbuf;
01397 }
01398
01399 if (NIL_P(port)) {
01400 strcpy(pbuf, "0");
01401 pptr = NULL;
01402 }
01403 else if (FIXNUM_P(port)) {
01404 snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
01405 pptr = pbuf;
01406 }
01407 else {
01408 strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
01409 pbuf[sizeof(pbuf) - 1] = '\0';
01410 pptr = pbuf;
01411 }
01412 hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
01413
01414 hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
01415 error = rb_getaddrinfo(hptr, pptr, &hints, &res);
01416 if (error) goto error_exit_addr;
01417 sap = res->ai->ai_addr;
01418 salen = res->ai->ai_addrlen;
01419 }
01420 else {
01421 rb_raise(rb_eTypeError, "expecting String or Array");
01422 }
01423
01424 call_nameinfo:
01425 error = rb_getnameinfo(sap, salen, hbuf, sizeof(hbuf),
01426 pbuf, sizeof(pbuf), fl);
01427 if (error) goto error_exit_name;
01428 if (res) {
01429 for (r = res->ai->ai_next; r; r = r->ai_next) {
01430 char hbuf2[1024], pbuf2[1024];
01431
01432 sap = r->ai_addr;
01433 salen = r->ai_addrlen;
01434 error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2),
01435 pbuf2, sizeof(pbuf2), fl);
01436 if (error) goto error_exit_name;
01437 if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
01438 rb_freeaddrinfo(res);
01439 rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
01440 }
01441 }
01442 rb_freeaddrinfo(res);
01443 }
01444 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
01445
01446 error_exit_addr:
01447 saved_errno = errno;
01448 if (res) rb_freeaddrinfo(res);
01449 errno = saved_errno;
01450 rsock_raise_socket_error("getaddrinfo", error);
01451
01452 error_exit_name:
01453 saved_errno = errno;
01454 if (res) rb_freeaddrinfo(res);
01455 errno = saved_errno;
01456 rsock_raise_socket_error("getnameinfo", error);
01457
01458 UNREACHABLE;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475 static VALUE
01476 sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
01477 {
01478 struct rb_addrinfo *res = rsock_addrinfo(host, port, 0, 0);
01479 VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen);
01480
01481 rb_freeaddrinfo(res);
01482 OBJ_INFECT(addr, port);
01483 OBJ_INFECT(addr, host);
01484
01485 return addr;
01486 }
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501 static VALUE
01502 sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
01503 {
01504 struct sockaddr_in * sockaddr;
01505 VALUE host;
01506
01507 sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
01508 if (RSTRING_LEN(addr) <
01509 (char*)&((struct sockaddr *)sockaddr)->sa_family +
01510 sizeof(((struct sockaddr *)sockaddr)->sa_family) -
01511 (char*)sockaddr)
01512 rb_raise(rb_eArgError, "too short sockaddr");
01513 if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
01514 #ifdef INET6
01515 && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
01516 #endif
01517 ) {
01518 #ifdef INET6
01519 rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
01520 #else
01521 rb_raise(rb_eArgError, "not an AF_INET sockaddr");
01522 #endif
01523 }
01524 host = rsock_make_ipaddr((struct sockaddr*)sockaddr, RSTRING_SOCKLEN(addr));
01525 OBJ_INFECT(host, addr);
01526 return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
01527 }
01528
01529 #ifdef HAVE_SYS_UN_H
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541 static VALUE
01542 sock_s_pack_sockaddr_un(VALUE self, VALUE path)
01543 {
01544 struct sockaddr_un sockaddr;
01545 VALUE addr;
01546
01547 StringValue(path);
01548 INIT_SOCKADDR_UN(&sockaddr, sizeof(struct sockaddr_un));
01549 if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
01550 rb_raise(rb_eArgError, "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
01551 (size_t)RSTRING_LEN(path), sizeof(sockaddr.sun_path));
01552 }
01553 memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
01554 addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path));
01555 OBJ_INFECT(addr, path);
01556
01557 return addr;
01558 }
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572 static VALUE
01573 sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
01574 {
01575 struct sockaddr_un * sockaddr;
01576 VALUE path;
01577
01578 sockaddr = (struct sockaddr_un*)SockAddrStringValuePtr(addr);
01579 if (RSTRING_LEN(addr) <
01580 (char*)&((struct sockaddr *)sockaddr)->sa_family +
01581 sizeof(((struct sockaddr *)sockaddr)->sa_family) -
01582 (char*)sockaddr)
01583 rb_raise(rb_eArgError, "too short sockaddr");
01584 if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
01585 rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
01586 }
01587 if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
01588 rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
01589 RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
01590 }
01591 path = rsock_unixpath_str(sockaddr, RSTRING_SOCKLEN(addr));
01592 OBJ_INFECT(path, addr);
01593 return path;
01594 }
01595 #endif
01596
01597 #if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) || defined(_WIN32)
01598
01599 static socklen_t
01600 sockaddr_len(struct sockaddr *addr)
01601 {
01602 if (addr == NULL)
01603 return 0;
01604
01605 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
01606 if (addr->sa_len != 0)
01607 return addr->sa_len;
01608 #endif
01609
01610 switch (addr->sa_family) {
01611 case AF_INET:
01612 return (socklen_t)sizeof(struct sockaddr_in);
01613
01614 #ifdef AF_INET6
01615 case AF_INET6:
01616 return (socklen_t)sizeof(struct sockaddr_in6);
01617 #endif
01618
01619 #ifdef HAVE_SYS_UN_H
01620 case AF_UNIX:
01621 return (socklen_t)sizeof(struct sockaddr_un);
01622 #endif
01623
01624 #ifdef AF_PACKET
01625 case AF_PACKET:
01626 return (socklen_t)(offsetof(struct sockaddr_ll, sll_addr) + ((struct sockaddr_ll *)addr)->sll_halen);
01627 #endif
01628
01629 default:
01630 return (socklen_t)(offsetof(struct sockaddr, sa_family) + sizeof(addr->sa_family));
01631 }
01632 }
01633
01634 socklen_t
01635 rsock_sockaddr_len(struct sockaddr *addr)
01636 {
01637 return sockaddr_len(addr);
01638 }
01639
01640 static VALUE
01641 sockaddr_obj(struct sockaddr *addr, socklen_t len)
01642 {
01643 #if defined(AF_INET6) && defined(__KAME__)
01644 struct sockaddr_in6 addr6;
01645 #endif
01646
01647 if (addr == NULL)
01648 return Qnil;
01649
01650 len = sockaddr_len(addr);
01651
01652 #if defined(__KAME__) && defined(AF_INET6)
01653 if (addr->sa_family == AF_INET6) {
01654
01655
01656
01657 len = (socklen_t)sizeof(struct sockaddr_in6);
01658 memcpy(&addr6, addr, len);
01659 addr = (struct sockaddr *)&addr6;
01660 if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
01661 addr6.sin6_scope_id == 0 &&
01662 (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
01663 addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
01664 addr6.sin6_addr.s6_addr[2] = 0;
01665 addr6.sin6_addr.s6_addr[3] = 0;
01666 }
01667 }
01668 #endif
01669
01670 return rsock_addrinfo_new(addr, len, addr->sa_family, 0, 0, Qnil, Qnil);
01671 }
01672
01673 VALUE
01674 rsock_sockaddr_obj(struct sockaddr *addr, socklen_t len)
01675 {
01676 return sockaddr_obj(addr, len);
01677 }
01678
01679 #endif
01680
01681 #if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)) || defined(SIOCGIFCONF) || defined(_WIN32)
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697 static VALUE
01698 socket_s_ip_address_list(VALUE self)
01699 {
01700 #if defined(HAVE_GETIFADDRS)
01701 struct ifaddrs *ifp = NULL;
01702 struct ifaddrs *p;
01703 int ret;
01704 VALUE list;
01705
01706 ret = getifaddrs(&ifp);
01707 if (ret == -1) {
01708 rb_sys_fail("getifaddrs");
01709 }
01710
01711 list = rb_ary_new();
01712 for (p = ifp; p; p = p->ifa_next) {
01713 if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
01714 struct sockaddr *addr = p->ifa_addr;
01715 #if defined(AF_INET6) && defined(__sun)
01716
01717
01718
01719
01720
01721 struct sockaddr_in6 addr6;
01722 if (addr->sa_family == AF_INET6) {
01723 socklen_t len = (socklen_t)sizeof(struct sockaddr_in6);
01724 memcpy(&addr6, addr, len);
01725 addr = (struct sockaddr *)&addr6;
01726 if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
01727 addr6.sin6_scope_id == 0) {
01728 unsigned int ifindex = if_nametoindex(p->ifa_name);
01729 if (ifindex != 0) {
01730 addr6.sin6_scope_id = ifindex;
01731 }
01732 }
01733 }
01734 #endif
01735 rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
01736 }
01737 }
01738
01739 freeifaddrs(ifp);
01740
01741 return list;
01742 #elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)
01743
01744
01745 int fd = -1;
01746 int ret;
01747 struct lifnum ln;
01748 struct lifconf lc;
01749 char *reason = NULL;
01750 int save_errno;
01751 int i;
01752 VALUE list = Qnil;
01753
01754 lc.lifc_buf = NULL;
01755
01756 fd = socket(AF_INET, SOCK_DGRAM, 0);
01757 if (fd == -1)
01758 rb_sys_fail("socket(2)");
01759
01760 memset(&ln, 0, sizeof(ln));
01761 ln.lifn_family = AF_UNSPEC;
01762
01763 ret = ioctl(fd, SIOCGLIFNUM, &ln);
01764 if (ret == -1) {
01765 reason = "SIOCGLIFNUM";
01766 goto finish;
01767 }
01768
01769 memset(&lc, 0, sizeof(lc));
01770 lc.lifc_family = AF_UNSPEC;
01771 lc.lifc_flags = 0;
01772 lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
01773 lc.lifc_req = xmalloc(lc.lifc_len);
01774
01775 ret = ioctl(fd, SIOCGLIFCONF, &lc);
01776 if (ret == -1) {
01777 reason = "SIOCGLIFCONF";
01778 goto finish;
01779 }
01780
01781 list = rb_ary_new();
01782 for (i = 0; i < ln.lifn_count; i++) {
01783 struct lifreq *req = &lc.lifc_req[i];
01784 if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
01785 if (req->lifr_addr.ss_family == AF_INET6 &&
01786 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
01787 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
01788 struct lifreq req2;
01789 memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
01790 ret = ioctl(fd, SIOCGLIFINDEX, &req2);
01791 if (ret == -1) {
01792 reason = "SIOCGLIFINDEX";
01793 goto finish;
01794 }
01795 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
01796 }
01797 rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr, req->lifr_addrlen));
01798 }
01799 }
01800
01801 finish:
01802 save_errno = errno;
01803 if (lc.lifc_buf != NULL)
01804 xfree(lc.lifc_req);
01805 if (fd != -1)
01806 close(fd);
01807 errno = save_errno;
01808
01809 if (reason)
01810 rb_sys_fail(reason);
01811 return list;
01812
01813 #elif defined(SIOCGIFCONF)
01814 int fd = -1;
01815 int ret;
01816 #define EXTRA_SPACE ((int)(sizeof(struct ifconf) + sizeof(union_sockaddr)))
01817 char initbuf[4096+EXTRA_SPACE];
01818 char *buf = initbuf;
01819 int bufsize;
01820 struct ifconf conf;
01821 struct ifreq *req;
01822 VALUE list = Qnil;
01823 const char *reason = NULL;
01824 int save_errno;
01825
01826 fd = socket(AF_INET, SOCK_DGRAM, 0);
01827 if (fd == -1)
01828 rb_sys_fail("socket(2)");
01829
01830 bufsize = sizeof(initbuf);
01831 buf = initbuf;
01832
01833 retry:
01834 conf.ifc_len = bufsize;
01835 conf.ifc_req = (struct ifreq *)buf;
01836
01837
01838
01839 ret = ioctl(fd, SIOCGIFCONF, &conf);
01840 if (ret == -1) {
01841 reason = "SIOCGIFCONF";
01842 goto finish;
01843 }
01844
01845
01846
01847 if (bufsize - EXTRA_SPACE < conf.ifc_len) {
01848 if (bufsize < conf.ifc_len) {
01849
01850 bufsize = conf.ifc_len + EXTRA_SPACE;
01851 }
01852 else {
01853 bufsize = bufsize << 1;
01854 }
01855 if (buf == initbuf)
01856 buf = NULL;
01857 buf = xrealloc(buf, bufsize);
01858 goto retry;
01859 }
01860
01861 close(fd);
01862 fd = -1;
01863
01864 list = rb_ary_new();
01865 req = conf.ifc_req;
01866 while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
01867 struct sockaddr *addr = &req->ifr_addr;
01868 if (IS_IP_FAMILY(addr->sa_family)) {
01869 rb_ary_push(list, sockaddr_obj(addr, sockaddr_len(addr)));
01870 }
01871 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
01872 # ifndef _SIZEOF_ADDR_IFREQ
01873 # define _SIZEOF_ADDR_IFREQ(r) \
01874 (sizeof(struct ifreq) + \
01875 (sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
01876 (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
01877 0))
01878 # endif
01879 req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
01880 #else
01881 req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
01882 #endif
01883 }
01884
01885 finish:
01886
01887 save_errno = errno;
01888 if (buf != initbuf)
01889 xfree(buf);
01890 if (fd != -1)
01891 close(fd);
01892 errno = save_errno;
01893
01894 if (reason)
01895 rb_sys_fail(reason);
01896 return list;
01897
01898 #undef EXTRA_SPACE
01899 #elif defined(_WIN32)
01900 typedef struct ip_adapter_unicast_address_st {
01901 unsigned LONG_LONG dummy0;
01902 struct ip_adapter_unicast_address_st *Next;
01903 struct {
01904 struct sockaddr *lpSockaddr;
01905 int iSockaddrLength;
01906 } Address;
01907 int dummy1;
01908 int dummy2;
01909 int dummy3;
01910 long dummy4;
01911 long dummy5;
01912 long dummy6;
01913 } ip_adapter_unicast_address_t;
01914 typedef struct ip_adapter_anycast_address_st {
01915 unsigned LONG_LONG dummy0;
01916 struct ip_adapter_anycast_address_st *Next;
01917 struct {
01918 struct sockaddr *lpSockaddr;
01919 int iSockaddrLength;
01920 } Address;
01921 } ip_adapter_anycast_address_t;
01922 typedef struct ip_adapter_addresses_st {
01923 unsigned LONG_LONG dummy0;
01924 struct ip_adapter_addresses_st *Next;
01925 void *dummy1;
01926 ip_adapter_unicast_address_t *FirstUnicastAddress;
01927 ip_adapter_anycast_address_t *FirstAnycastAddress;
01928 void *dummy2;
01929 void *dummy3;
01930 void *dummy4;
01931 void *dummy5;
01932 void *dummy6;
01933 BYTE dummy7[8];
01934 DWORD dummy8;
01935 DWORD dummy9;
01936 DWORD dummy10;
01937 DWORD IfType;
01938 int OperStatus;
01939 DWORD dummy12;
01940 DWORD dummy13[16];
01941 void *dummy14;
01942 } ip_adapter_addresses_t;
01943 typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
01944 HMODULE h;
01945 GetAdaptersAddresses_t pGetAdaptersAddresses;
01946 ULONG len;
01947 DWORD ret;
01948 ip_adapter_addresses_t *adapters;
01949 VALUE list;
01950
01951 h = LoadLibrary("iphlpapi.dll");
01952 if (!h)
01953 rb_notimplement();
01954 pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
01955 if (!pGetAdaptersAddresses) {
01956 FreeLibrary(h);
01957 rb_notimplement();
01958 }
01959
01960 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
01961 if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
01962 errno = rb_w32_map_errno(ret);
01963 FreeLibrary(h);
01964 rb_sys_fail("GetAdaptersAddresses");
01965 }
01966 adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
01967 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
01968 if (ret != ERROR_SUCCESS) {
01969 errno = rb_w32_map_errno(ret);
01970 FreeLibrary(h);
01971 rb_sys_fail("GetAdaptersAddresses");
01972 }
01973
01974 list = rb_ary_new();
01975 for (; adapters; adapters = adapters->Next) {
01976 ip_adapter_unicast_address_t *uni;
01977 ip_adapter_anycast_address_t *any;
01978 if (adapters->OperStatus != 1)
01979 continue;
01980 for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
01981 #ifndef INET6
01982 if (uni->Address.lpSockaddr->sa_family == AF_INET)
01983 #else
01984 if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
01985 #endif
01986 rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr, uni->Address.iSockaddrLength));
01987 }
01988 for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
01989 #ifndef INET6
01990 if (any->Address.lpSockaddr->sa_family == AF_INET)
01991 #else
01992 if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
01993 #endif
01994 rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr, any->Address.iSockaddrLength));
01995 }
01996 }
01997
01998 FreeLibrary(h);
01999 return list;
02000 #endif
02001 }
02002 #else
02003 #define socket_s_ip_address_list rb_f_notimplement
02004 #endif
02005
02006 void
02007 Init_socket()
02008 {
02009 rsock_init_basicsocket();
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043
02044
02045
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122
02123
02124
02125
02126 rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
02127
02128 rsock_init_socket_init();
02129
02130 rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
02131 rb_define_method(rb_cSocket, "connect", sock_connect, 1);
02132 rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
02133 rb_define_method(rb_cSocket, "bind", sock_bind, 1);
02134 rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
02135 rb_define_method(rb_cSocket, "accept", sock_accept, 0);
02136 rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
02137 rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
02138
02139 rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
02140 rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
02141
02142 rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1);
02143 rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1);
02144 rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
02145 rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
02146 rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
02147 rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);
02148 rb_define_singleton_method(rb_cSocket, "getservbyport", sock_s_getservbyport, -1);
02149 rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
02150 rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
02151 rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
02152 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
02153 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
02154 #ifdef HAVE_SYS_UN_H
02155 rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
02156 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
02157 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
02158 #endif
02159
02160 rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0);
02161 }
02162