00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "rubysocket.h"
00012
00013 static void
00014 setup_domain_and_type(VALUE domain, int *dv, VALUE type, int *tv)
00015 {
00016 *dv = rsock_family_arg(domain);
00017 *tv = rsock_socktype_arg(type);
00018 }
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 static VALUE
00040 sock_initialize(int argc, VALUE *argv, VALUE sock)
00041 {
00042 VALUE domain, type, protocol;
00043 int fd;
00044 int d, t;
00045
00046 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
00047 if (NIL_P(protocol))
00048 protocol = INT2FIX(0);
00049
00050 rb_secure(3);
00051 setup_domain_and_type(domain, &d, type, &t);
00052 fd = rsock_socket(d, t, NUM2INT(protocol));
00053 if (fd < 0) rb_sys_fail("socket(2)");
00054
00055 return rsock_init_sock(sock, fd);
00056 }
00057
00058 #if defined HAVE_SOCKETPAIR
00059 static VALUE
00060 io_call_close(VALUE io)
00061 {
00062 return rb_funcall(io, rb_intern("close"), 0, 0);
00063 }
00064
00065 static VALUE
00066 io_close(VALUE io)
00067 {
00068 return rb_rescue(io_call_close, io, 0, 0);
00069 }
00070
00071 static VALUE
00072 pair_yield(VALUE pair)
00073 {
00074 return rb_ensure(rb_yield, pair, io_close, rb_ary_entry(pair, 1));
00075 }
00076 #endif
00077
00078 #if defined HAVE_SOCKETPAIR
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 VALUE
00101 rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
00102 {
00103 VALUE domain, type, protocol;
00104 int d, t, p, sp[2];
00105 int ret;
00106 VALUE s1, s2, r;
00107
00108 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
00109 if (NIL_P(protocol))
00110 protocol = INT2FIX(0);
00111
00112 setup_domain_and_type(domain, &d, type, &t);
00113 p = NUM2INT(protocol);
00114 ret = socketpair(d, t, p, sp);
00115 if (ret < 0 && (errno == EMFILE || errno == ENFILE)) {
00116 rb_gc();
00117 ret = socketpair(d, t, p, sp);
00118 }
00119 if (ret < 0) {
00120 rb_sys_fail("socketpair(2)");
00121 }
00122
00123 s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
00124 s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
00125 r = rb_assoc_new(s1, s2);
00126 if (rb_block_given_p()) {
00127 return rb_ensure(pair_yield, r, io_close, s1);
00128 }
00129 return r;
00130 }
00131 #else
00132 #define rsock_sock_s_socketpair rb_f_notimplement
00133 #endif
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 static VALUE
00247 sock_connect(VALUE sock, VALUE addr)
00248 {
00249 rb_io_t *fptr;
00250 int fd, n;
00251
00252 SockAddrStringValue(addr);
00253 addr = rb_str_new4(addr);
00254 GetOpenFile(sock, fptr);
00255 fd = fptr->fd;
00256 n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr), 0);
00257 if (n < 0) {
00258 rb_sys_fail("connect(2)");
00259 }
00260
00261 return INT2FIX(n);
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 static VALUE
00307 sock_connect_nonblock(VALUE sock, VALUE addr)
00308 {
00309 rb_io_t *fptr;
00310 int n;
00311
00312 SockAddrStringValue(addr);
00313 addr = rb_str_new4(addr);
00314 GetOpenFile(sock, fptr);
00315 rb_io_set_nonblock(fptr);
00316 n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr));
00317 if (n < 0) {
00318 if (errno == EINPROGRESS)
00319 rb_mod_sys_fail(rb_mWaitWritable, "connect(2) would block");
00320 rb_sys_fail("connect(2)");
00321 }
00322
00323 return INT2FIX(n);
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
00407
00408
00409
00410
00411
00412 static VALUE
00413 sock_bind(VALUE sock, VALUE addr)
00414 {
00415 rb_io_t *fptr;
00416
00417 SockAddrStringValue(addr);
00418 GetOpenFile(sock, fptr);
00419 if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr)) < 0)
00420 rb_sys_fail("bind(2)");
00421
00422 return INT2FIX(0);
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
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 VALUE
00496 rsock_sock_listen(VALUE sock, VALUE log)
00497 {
00498 rb_io_t *fptr;
00499 int backlog;
00500
00501 rb_secure(4);
00502 backlog = NUM2INT(log);
00503 GetOpenFile(sock, fptr);
00504 if (listen(fptr->fd, backlog) < 0)
00505 rb_sys_fail("listen(2)");
00506
00507 return INT2FIX(0);
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
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
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 static VALUE
00616 sock_recvfrom(int argc, VALUE *argv, VALUE sock)
00617 {
00618 return rsock_s_recvfrom(sock, argc, argv, RECV_SOCKET);
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
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 static VALUE
00684 sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
00685 {
00686 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
00687 }
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703 static VALUE
00704 sock_accept(VALUE sock)
00705 {
00706 rb_io_t *fptr;
00707 VALUE sock2;
00708 struct sockaddr_storage buf;
00709 socklen_t len = (socklen_t)sizeof buf;
00710
00711 GetOpenFile(sock, fptr);
00712 sock2 = rsock_s_accept(rb_cSocket,fptr->fd,(struct sockaddr*)&buf,&len);
00713
00714 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
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 static VALUE
00769 sock_accept_nonblock(VALUE sock)
00770 {
00771 rb_io_t *fptr;
00772 VALUE sock2;
00773 struct sockaddr_storage buf;
00774 socklen_t len = (socklen_t)sizeof buf;
00775
00776 GetOpenFile(sock, fptr);
00777 sock2 = rsock_s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)&buf, &len);
00778 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
00779 }
00780
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 static VALUE
00820 sock_sysaccept(VALUE sock)
00821 {
00822 rb_io_t *fptr;
00823 VALUE sock2;
00824 struct sockaddr_storage buf;
00825 socklen_t len = (socklen_t)sizeof buf;
00826
00827 GetOpenFile(sock, fptr);
00828 sock2 = rsock_s_accept(0,fptr->fd,(struct sockaddr*)&buf,&len);
00829
00830 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
00831 }
00832
00833 #ifdef HAVE_GETHOSTNAME
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845 static VALUE
00846 sock_gethostname(VALUE obj)
00847 {
00848 #ifndef HOST_NAME_MAX
00849 # define HOST_NAME_MAX 1024
00850 #endif
00851 char buf[HOST_NAME_MAX+1];
00852
00853 rb_secure(3);
00854 if (gethostname(buf, (int)sizeof buf - 1) < 0)
00855 rb_sys_fail("gethostname");
00856
00857 buf[sizeof buf - 1] = '\0';
00858 return rb_str_new2(buf);
00859 }
00860 #else
00861 #ifdef HAVE_UNAME
00862
00863 #include <sys/utsname.h>
00864
00865 static VALUE
00866 sock_gethostname(VALUE obj)
00867 {
00868 struct utsname un;
00869
00870 rb_secure(3);
00871 uname(&un);
00872 return rb_str_new2(un.nodename);
00873 }
00874 #else
00875 #define sock_gethostname rb_f_notimplement
00876 #endif
00877 #endif
00878
00879 static VALUE
00880 make_addrinfo(struct addrinfo *res0, int norevlookup)
00881 {
00882 VALUE base, ary;
00883 struct addrinfo *res;
00884
00885 if (res0 == NULL) {
00886 rb_raise(rb_eSocket, "host not found");
00887 }
00888 base = rb_ary_new();
00889 for (res = res0; res; res = res->ai_next) {
00890 ary = rsock_ipaddr(res->ai_addr, norevlookup);
00891 if (res->ai_canonname) {
00892 RARRAY_PTR(ary)[2] = rb_str_new2(res->ai_canonname);
00893 }
00894 rb_ary_push(ary, INT2FIX(res->ai_family));
00895 rb_ary_push(ary, INT2FIX(res->ai_socktype));
00896 rb_ary_push(ary, INT2FIX(res->ai_protocol));
00897 rb_ary_push(base, ary);
00898 }
00899 return base;
00900 }
00901
00902 static VALUE
00903 sock_sockaddr(struct sockaddr *addr, size_t len)
00904 {
00905 char *ptr;
00906
00907 switch (addr->sa_family) {
00908 case AF_INET:
00909 ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
00910 len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
00911 break;
00912 #ifdef AF_INET6
00913 case AF_INET6:
00914 ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
00915 len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
00916 break;
00917 #endif
00918 default:
00919 rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
00920 break;
00921 }
00922 return rb_str_new(ptr, len);
00923 }
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934 static VALUE
00935 sock_s_gethostbyname(VALUE obj, VALUE host)
00936 {
00937 rb_secure(3);
00938 return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950 static VALUE
00951 sock_s_gethostbyaddr(int argc, VALUE *argv)
00952 {
00953 VALUE addr, family;
00954 struct hostent *h;
00955 struct sockaddr *sa;
00956 char **pch;
00957 VALUE ary, names;
00958 int t = AF_INET;
00959
00960 rb_scan_args(argc, argv, "11", &addr, &family);
00961 sa = (struct sockaddr*)StringValuePtr(addr);
00962 if (!NIL_P(family)) {
00963 t = rsock_family_arg(family);
00964 }
00965 #ifdef AF_INET6
00966 else if (RSTRING_LEN(addr) == 16) {
00967 t = AF_INET6;
00968 }
00969 #endif
00970 h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_LENINT(addr), t);
00971 if (h == NULL) {
00972 #ifdef HAVE_HSTRERROR
00973 extern int h_errno;
00974 rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
00975 #else
00976 rb_raise(rb_eSocket, "host not found");
00977 #endif
00978 }
00979 ary = rb_ary_new();
00980 rb_ary_push(ary, rb_str_new2(h->h_name));
00981 names = rb_ary_new();
00982 rb_ary_push(ary, names);
00983 if (h->h_aliases != NULL) {
00984 for (pch = h->h_aliases; *pch; pch++) {
00985 rb_ary_push(names, rb_str_new2(*pch));
00986 }
00987 }
00988 rb_ary_push(ary, INT2NUM(h->h_addrtype));
00989 #ifdef h_addr
00990 for (pch = h->h_addr_list; *pch; pch++) {
00991 rb_ary_push(ary, rb_str_new(*pch, h->h_length));
00992 }
00993 #else
00994 rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
00995 #endif
00996
00997 return ary;
00998 }
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 static VALUE
01014 sock_s_getservbyname(int argc, VALUE *argv)
01015 {
01016 VALUE service, proto;
01017 struct servent *sp;
01018 long port;
01019 const char *servicename, *protoname = "tcp";
01020
01021 rb_scan_args(argc, argv, "11", &service, &proto);
01022 StringValue(service);
01023 if (!NIL_P(proto)) StringValue(proto);
01024 servicename = StringValueCStr(service);
01025 if (!NIL_P(proto)) protoname = StringValueCStr(proto);
01026 sp = getservbyname(servicename, protoname);
01027 if (sp) {
01028 port = ntohs(sp->s_port);
01029 }
01030 else {
01031 char *end;
01032
01033 port = STRTOUL(servicename, &end, 0);
01034 if (*end != '\0') {
01035 rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
01036 }
01037 }
01038 return INT2FIX(port);
01039 }
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054 static VALUE
01055 sock_s_getservbyport(int argc, VALUE *argv)
01056 {
01057 VALUE port, proto;
01058 struct servent *sp;
01059 long portnum;
01060 const char *protoname = "tcp";
01061
01062 rb_scan_args(argc, argv, "11", &port, &proto);
01063 portnum = NUM2LONG(port);
01064 if (portnum != (uint16_t)portnum) {
01065 const char *s = portnum > 0 ? "big" : "small";
01066 rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
01067 }
01068 if (!NIL_P(proto)) protoname = StringValueCStr(proto);
01069
01070 sp = getservbyport((int)htons((uint16_t)portnum), protoname);
01071 if (!sp) {
01072 rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
01073 }
01074 return rb_tainted_str_new2(sp->s_name);
01075 }
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110 static VALUE
01111 sock_s_getaddrinfo(int argc, VALUE *argv)
01112 {
01113 VALUE host, port, family, socktype, protocol, flags, ret, revlookup;
01114 struct addrinfo hints, *res;
01115 int norevlookup;
01116
01117 rb_scan_args(argc, argv, "25", &host, &port, &family, &socktype, &protocol, &flags, &revlookup);
01118
01119 MEMZERO(&hints, struct addrinfo, 1);
01120 hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
01121
01122 if (!NIL_P(socktype)) {
01123 hints.ai_socktype = rsock_socktype_arg(socktype);
01124 }
01125 if (!NIL_P(protocol)) {
01126 hints.ai_protocol = NUM2INT(protocol);
01127 }
01128 if (!NIL_P(flags)) {
01129 hints.ai_flags = NUM2INT(flags);
01130 }
01131 if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
01132 norevlookup = rsock_do_not_reverse_lookup;
01133 }
01134 res = rsock_getaddrinfo(host, port, &hints, 0);
01135
01136 ret = make_addrinfo(res, norevlookup);
01137 freeaddrinfo(res);
01138 return ret;
01139 }
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162 static VALUE
01163 sock_s_getnameinfo(int argc, VALUE *argv)
01164 {
01165 VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
01166 char *hptr, *pptr;
01167 char hbuf[1024], pbuf[1024];
01168 int fl;
01169 struct addrinfo hints, *res = NULL, *r;
01170 int error;
01171 struct sockaddr_storage ss;
01172 struct sockaddr *sap;
01173
01174 sa = flags = Qnil;
01175 rb_scan_args(argc, argv, "11", &sa, &flags);
01176
01177 fl = 0;
01178 if (!NIL_P(flags)) {
01179 fl = NUM2INT(flags);
01180 }
01181 tmp = rb_check_sockaddr_string_type(sa);
01182 if (!NIL_P(tmp)) {
01183 sa = tmp;
01184 if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
01185 rb_raise(rb_eTypeError, "sockaddr length too big");
01186 }
01187 memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
01188 if ((size_t)RSTRING_LEN(sa) != SS_LEN(&ss)) {
01189 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
01190 }
01191 sap = (struct sockaddr*)&ss;
01192 goto call_nameinfo;
01193 }
01194 tmp = rb_check_array_type(sa);
01195 if (!NIL_P(tmp)) {
01196 sa = tmp;
01197 MEMZERO(&hints, struct addrinfo, 1);
01198 if (RARRAY_LEN(sa) == 3) {
01199 af = RARRAY_PTR(sa)[0];
01200 port = RARRAY_PTR(sa)[1];
01201 host = RARRAY_PTR(sa)[2];
01202 }
01203 else if (RARRAY_LEN(sa) >= 4) {
01204 af = RARRAY_PTR(sa)[0];
01205 port = RARRAY_PTR(sa)[1];
01206 host = RARRAY_PTR(sa)[3];
01207 if (NIL_P(host)) {
01208 host = RARRAY_PTR(sa)[2];
01209 }
01210 else {
01211
01212
01213
01214
01215 #ifdef AI_NUMERICHOST
01216 hints.ai_flags |= AI_NUMERICHOST;
01217 #endif
01218 }
01219 }
01220 else {
01221 rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
01222 RARRAY_LEN(sa));
01223 }
01224
01225 if (NIL_P(host)) {
01226 hptr = NULL;
01227 }
01228 else {
01229 strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
01230 hbuf[sizeof(hbuf) - 1] = '\0';
01231 hptr = hbuf;
01232 }
01233
01234 if (NIL_P(port)) {
01235 strcpy(pbuf, "0");
01236 pptr = NULL;
01237 }
01238 else if (FIXNUM_P(port)) {
01239 snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
01240 pptr = pbuf;
01241 }
01242 else {
01243 strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
01244 pbuf[sizeof(pbuf) - 1] = '\0';
01245 pptr = pbuf;
01246 }
01247 hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
01248
01249 hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
01250 error = rb_getaddrinfo(hptr, pptr, &hints, &res);
01251 if (error) goto error_exit_addr;
01252 sap = res->ai_addr;
01253 }
01254 else {
01255 rb_raise(rb_eTypeError, "expecting String or Array");
01256 }
01257
01258 call_nameinfo:
01259 error = rb_getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
01260 pbuf, sizeof(pbuf), fl);
01261 if (error) goto error_exit_name;
01262 if (res) {
01263 for (r = res->ai_next; r; r = r->ai_next) {
01264 char hbuf2[1024], pbuf2[1024];
01265
01266 sap = r->ai_addr;
01267 error = rb_getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
01268 pbuf2, sizeof(pbuf2), fl);
01269 if (error) goto error_exit_name;
01270 if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
01271 freeaddrinfo(res);
01272 rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
01273 }
01274 }
01275 freeaddrinfo(res);
01276 }
01277 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
01278
01279 error_exit_addr:
01280 if (res) freeaddrinfo(res);
01281 rsock_raise_socket_error("getaddrinfo", error);
01282
01283 error_exit_name:
01284 if (res) freeaddrinfo(res);
01285 rsock_raise_socket_error("getnameinfo", error);
01286 }
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302 static VALUE
01303 sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
01304 {
01305 struct addrinfo *res = rsock_addrinfo(host, port, 0, 0);
01306 VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
01307
01308 freeaddrinfo(res);
01309 OBJ_INFECT(addr, port);
01310 OBJ_INFECT(addr, host);
01311
01312 return addr;
01313 }
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 static VALUE
01329 sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
01330 {
01331 struct sockaddr_in * sockaddr;
01332 VALUE host;
01333
01334 sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
01335 if (RSTRING_LEN(addr) <
01336 (char*)&((struct sockaddr *)sockaddr)->sa_family +
01337 sizeof(((struct sockaddr *)sockaddr)->sa_family) -
01338 (char*)sockaddr)
01339 rb_raise(rb_eArgError, "too short sockaddr");
01340 if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
01341 #ifdef INET6
01342 && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
01343 #endif
01344 ) {
01345 #ifdef INET6
01346 rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
01347 #else
01348 rb_raise(rb_eArgError, "not an AF_INET sockaddr");
01349 #endif
01350 }
01351 host = rsock_make_ipaddr((struct sockaddr*)sockaddr);
01352 OBJ_INFECT(host, addr);
01353 return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
01354 }
01355
01356 #ifdef HAVE_SYS_UN_H
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368 static VALUE
01369 sock_s_pack_sockaddr_un(VALUE self, VALUE path)
01370 {
01371 struct sockaddr_un sockaddr;
01372 char *sun_path;
01373 VALUE addr;
01374
01375 MEMZERO(&sockaddr, struct sockaddr_un, 1);
01376 sockaddr.sun_family = AF_UNIX;
01377 sun_path = StringValueCStr(path);
01378 if (sizeof(sockaddr.sun_path) <= strlen(sun_path)) {
01379 rb_raise(rb_eArgError, "too long unix socket path (max: %dbytes)",
01380 (int)sizeof(sockaddr.sun_path)-1);
01381 }
01382 strncpy(sockaddr.sun_path, sun_path, sizeof(sockaddr.sun_path)-1);
01383 addr = rb_str_new((char*)&sockaddr, sizeof(sockaddr));
01384 OBJ_INFECT(addr, path);
01385
01386 return addr;
01387 }
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401 static VALUE
01402 sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
01403 {
01404 struct sockaddr_un * sockaddr;
01405 const char *sun_path;
01406 VALUE path;
01407
01408 sockaddr = (struct sockaddr_un*)SockAddrStringValuePtr(addr);
01409 if (RSTRING_LEN(addr) <
01410 (char*)&((struct sockaddr *)sockaddr)->sa_family +
01411 sizeof(((struct sockaddr *)sockaddr)->sa_family) -
01412 (char*)sockaddr)
01413 rb_raise(rb_eArgError, "too short sockaddr");
01414 if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
01415 rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
01416 }
01417 if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
01418 rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
01419 RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
01420 }
01421 sun_path = rsock_unixpath(sockaddr, RSTRING_LENINT(addr));
01422 if (sizeof(struct sockaddr_un) == RSTRING_LEN(addr) &&
01423 sun_path == sockaddr->sun_path &&
01424 sun_path + strlen(sun_path) == RSTRING_PTR(addr) + RSTRING_LEN(addr)) {
01425 rb_raise(rb_eArgError, "sockaddr_un.sun_path not NUL terminated");
01426 }
01427 path = rb_str_new2(sun_path);
01428 OBJ_INFECT(path, addr);
01429 return path;
01430 }
01431 #endif
01432
01433 #if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) || defined(_WIN32)
01434 static VALUE
01435 sockaddr_obj(struct sockaddr *addr)
01436 {
01437 socklen_t len;
01438 #if defined(AF_INET6) && defined(__KAME__)
01439 struct sockaddr_in6 addr6;
01440 #endif
01441
01442 if (addr == NULL)
01443 return Qnil;
01444
01445 switch (addr->sa_family) {
01446 case AF_INET:
01447 len = (socklen_t)sizeof(struct sockaddr_in);
01448 break;
01449
01450 #ifdef AF_INET6
01451 case AF_INET6:
01452 len = (socklen_t)sizeof(struct sockaddr_in6);
01453 # ifdef __KAME__
01454
01455
01456
01457 memcpy(&addr6, addr, len);
01458 addr = (struct sockaddr *)&addr6;
01459 if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
01460 addr6.sin6_scope_id == 0 &&
01461 (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
01462 addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
01463 addr6.sin6_addr.s6_addr[2] = 0;
01464 addr6.sin6_addr.s6_addr[3] = 0;
01465 }
01466 # endif
01467 break;
01468 #endif
01469
01470 #ifdef HAVE_SYS_UN_H
01471 case AF_UNIX:
01472 len = (socklen_t)sizeof(struct sockaddr_un);
01473 break;
01474 #endif
01475
01476 default:
01477 len = (socklen_t)sizeof(struct sockaddr_in);
01478 break;
01479 }
01480 #ifdef SA_LEN
01481 if (len < (socklen_t)SA_LEN(addr))
01482 len = (socklen_t)SA_LEN(addr);
01483 #endif
01484
01485 return rsock_addrinfo_new(addr, len, addr->sa_family, 0, 0, Qnil, Qnil);
01486 }
01487 #endif
01488
01489 #if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)) || defined(SIOCGIFCONF) || defined(_WIN32)
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505 static VALUE
01506 socket_s_ip_address_list(VALUE self)
01507 {
01508 #if defined(HAVE_GETIFADDRS)
01509 struct ifaddrs *ifp = NULL;
01510 struct ifaddrs *p;
01511 int ret;
01512 VALUE list;
01513
01514 ret = getifaddrs(&ifp);
01515 if (ret == -1) {
01516 rb_sys_fail("getifaddrs");
01517 }
01518
01519 list = rb_ary_new();
01520 for (p = ifp; p; p = p->ifa_next) {
01521 if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
01522 rb_ary_push(list, sockaddr_obj(p->ifa_addr));
01523 }
01524 }
01525
01526 freeifaddrs(ifp);
01527
01528 return list;
01529 #elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)
01530
01531
01532 int fd = -1;
01533 int ret;
01534 struct lifnum ln;
01535 struct lifconf lc;
01536 char *reason = NULL;
01537 int save_errno;
01538 int i;
01539 VALUE list = Qnil;
01540
01541 lc.lifc_buf = NULL;
01542
01543 fd = socket(AF_INET, SOCK_DGRAM, 0);
01544 if (fd == -1)
01545 rb_sys_fail("socket");
01546
01547 memset(&ln, 0, sizeof(ln));
01548 ln.lifn_family = AF_UNSPEC;
01549
01550 ret = ioctl(fd, SIOCGLIFNUM, &ln);
01551 if (ret == -1) {
01552 reason = "SIOCGLIFNUM";
01553 goto finish;
01554 }
01555
01556 memset(&lc, 0, sizeof(lc));
01557 lc.lifc_family = AF_UNSPEC;
01558 lc.lifc_flags = 0;
01559 lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
01560 lc.lifc_req = xmalloc(lc.lifc_len);
01561
01562 ret = ioctl(fd, SIOCGLIFCONF, &lc);
01563 if (ret == -1) {
01564 reason = "SIOCGLIFCONF";
01565 goto finish;
01566 }
01567
01568 list = rb_ary_new();
01569 for (i = 0; i < ln.lifn_count; i++) {
01570 struct lifreq *req = &lc.lifc_req[i];
01571 if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
01572 if (req->lifr_addr.ss_family == AF_INET6 &&
01573 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
01574 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
01575 struct lifreq req2;
01576 memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
01577 ret = ioctl(fd, SIOCGLIFINDEX, &req2);
01578 if (ret == -1) {
01579 reason = "SIOCGLIFINDEX";
01580 goto finish;
01581 }
01582 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
01583 }
01584 rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr));
01585 }
01586 }
01587
01588 finish:
01589 save_errno = errno;
01590 if (lc.lifc_buf != NULL)
01591 xfree(lc.lifc_req);
01592 if (fd != -1)
01593 close(fd);
01594 errno = save_errno;
01595
01596 if (reason)
01597 rb_sys_fail(reason);
01598 return list;
01599
01600 #elif defined(SIOCGIFCONF)
01601 int fd = -1;
01602 int ret;
01603 #define EXTRA_SPACE (sizeof(struct ifconf) + sizeof(struct sockaddr_storage))
01604 char initbuf[4096+EXTRA_SPACE];
01605 char *buf = initbuf;
01606 int bufsize;
01607 struct ifconf conf;
01608 struct ifreq *req;
01609 VALUE list = Qnil;
01610 const char *reason = NULL;
01611 int save_errno;
01612
01613 fd = socket(AF_INET, SOCK_DGRAM, 0);
01614 if (fd == -1)
01615 rb_sys_fail("socket");
01616
01617 bufsize = sizeof(initbuf);
01618 buf = initbuf;
01619
01620 retry:
01621 conf.ifc_len = bufsize;
01622 conf.ifc_req = (struct ifreq *)buf;
01623
01624
01625
01626 ret = ioctl(fd, SIOCGIFCONF, &conf);
01627 if (ret == -1) {
01628 reason = "SIOCGIFCONF";
01629 goto finish;
01630 }
01631
01632
01633
01634 if (bufsize - EXTRA_SPACE < conf.ifc_len) {
01635 if (bufsize < conf.ifc_len) {
01636
01637 bufsize = conf.ifc_len + EXTRA_SPACE;
01638 }
01639 else {
01640 bufsize = bufsize << 1;
01641 }
01642 if (buf == initbuf)
01643 buf = NULL;
01644 buf = xrealloc(buf, bufsize);
01645 goto retry;
01646 }
01647
01648 close(fd);
01649 fd = -1;
01650
01651 list = rb_ary_new();
01652 req = conf.ifc_req;
01653 while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
01654 struct sockaddr *addr = &req->ifr_addr;
01655 if (IS_IP_FAMILY(addr->sa_family)) {
01656 rb_ary_push(list, sockaddr_obj(addr));
01657 }
01658 #ifdef HAVE_SA_LEN
01659 # ifndef _SIZEOF_ADDR_IFREQ
01660 # define _SIZEOF_ADDR_IFREQ(r) \
01661 (sizeof(struct ifreq) + \
01662 (sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
01663 (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
01664 0))
01665 # endif
01666 req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
01667 #else
01668 req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
01669 #endif
01670 }
01671
01672 finish:
01673
01674 save_errno = errno;
01675 if (buf != initbuf)
01676 xfree(buf);
01677 if (fd != -1)
01678 close(fd);
01679 errno = save_errno;
01680
01681 if (reason)
01682 rb_sys_fail(reason);
01683 return list;
01684
01685 #undef EXTRA_SPACE
01686 #elif defined(_WIN32)
01687 typedef struct ip_adapter_unicast_address_st {
01688 unsigned LONG_LONG dummy0;
01689 struct ip_adapter_unicast_address_st *Next;
01690 struct {
01691 struct sockaddr *lpSockaddr;
01692 int iSockaddrLength;
01693 } Address;
01694 int dummy1;
01695 int dummy2;
01696 int dummy3;
01697 long dummy4;
01698 long dummy5;
01699 long dummy6;
01700 } ip_adapter_unicast_address_t;
01701 typedef struct ip_adapter_anycast_address_st {
01702 unsigned LONG_LONG dummy0;
01703 struct ip_adapter_anycast_address_st *Next;
01704 struct {
01705 struct sockaddr *lpSockaddr;
01706 int iSockaddrLength;
01707 } Address;
01708 } ip_adapter_anycast_address_t;
01709 typedef struct ip_adapter_addresses_st {
01710 unsigned LONG_LONG dummy0;
01711 struct ip_adapter_addresses_st *Next;
01712 void *dummy1;
01713 ip_adapter_unicast_address_t *FirstUnicastAddress;
01714 ip_adapter_anycast_address_t *FirstAnycastAddress;
01715 void *dummy2;
01716 void *dummy3;
01717 void *dummy4;
01718 void *dummy5;
01719 void *dummy6;
01720 BYTE dummy7[8];
01721 DWORD dummy8;
01722 DWORD dummy9;
01723 DWORD dummy10;
01724 DWORD IfType;
01725 int OperStatus;
01726 DWORD dummy12;
01727 DWORD dummy13[16];
01728 void *dummy14;
01729 } ip_adapter_addresses_t;
01730 typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
01731 HMODULE h;
01732 GetAdaptersAddresses_t pGetAdaptersAddresses;
01733 ULONG len;
01734 DWORD ret;
01735 ip_adapter_addresses_t *adapters;
01736 VALUE list;
01737
01738 h = LoadLibrary("iphlpapi.dll");
01739 if (!h)
01740 rb_notimplement();
01741 pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
01742 if (!pGetAdaptersAddresses) {
01743 FreeLibrary(h);
01744 rb_notimplement();
01745 }
01746
01747 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
01748 if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
01749 errno = rb_w32_map_errno(ret);
01750 FreeLibrary(h);
01751 rb_sys_fail("GetAdaptersAddresses");
01752 }
01753 adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
01754 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
01755 if (ret != ERROR_SUCCESS) {
01756 errno = rb_w32_map_errno(ret);
01757 FreeLibrary(h);
01758 rb_sys_fail("GetAdaptersAddresses");
01759 }
01760
01761 list = rb_ary_new();
01762 for (; adapters; adapters = adapters->Next) {
01763 ip_adapter_unicast_address_t *uni;
01764 ip_adapter_anycast_address_t *any;
01765 if (adapters->OperStatus != 1)
01766 continue;
01767 for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
01768 #ifndef INET6
01769 if (uni->Address.lpSockaddr->sa_family == AF_INET)
01770 #else
01771 if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
01772 #endif
01773 rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr));
01774 }
01775 for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
01776 #ifndef INET6
01777 if (any->Address.lpSockaddr->sa_family == AF_INET)
01778 #else
01779 if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
01780 #endif
01781 rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr));
01782 }
01783 }
01784
01785 FreeLibrary(h);
01786 return list;
01787 #endif
01788 }
01789 #else
01790 #define socket_s_ip_address_list rb_f_notimplement
01791 #endif
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 void
01831 Init_socket()
01832 {
01833 rsock_init_basicsocket();
01834
01835 rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
01836
01837 rsock_init_socket_init();
01838
01839 rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
01840 rb_define_method(rb_cSocket, "connect", sock_connect, 1);
01841 rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
01842 rb_define_method(rb_cSocket, "bind", sock_bind, 1);
01843 rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
01844 rb_define_method(rb_cSocket, "accept", sock_accept, 0);
01845 rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
01846 rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
01847
01848 rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
01849 rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
01850
01851 rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1);
01852 rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1);
01853 rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
01854 rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
01855 rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
01856 rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);
01857 rb_define_singleton_method(rb_cSocket, "getservbyport", sock_s_getservbyport, -1);
01858 rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
01859 rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
01860 rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
01861 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
01862 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
01863 #ifdef HAVE_SYS_UN_H
01864 rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
01865 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
01866 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
01867 #endif
01868
01869 rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0);
01870 }
01871