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 static VALUE
00039 sock_initialize(int argc, VALUE *argv, VALUE sock)
00040 {
00041 VALUE domain, type, protocol;
00042 int fd;
00043 int d, t;
00044
00045 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
00046 if (NIL_P(protocol))
00047 protocol = INT2FIX(0);
00048
00049 rb_secure(3);
00050 setup_domain_and_type(domain, &d, type, &t);
00051 fd = rsock_socket(d, t, NUM2INT(protocol));
00052 if (fd < 0) rb_sys_fail("socket(2)");
00053
00054 return rsock_init_sock(sock, fd);
00055 }
00056
00057 #if defined HAVE_SOCKETPAIR
00058 static VALUE
00059 io_call_close(VALUE io)
00060 {
00061 return rb_funcall(io, rb_intern("close"), 0, 0);
00062 }
00063
00064 static VALUE
00065 io_close(VALUE io)
00066 {
00067 return rb_rescue(io_call_close, io, 0, 0);
00068 }
00069
00070 static VALUE
00071 pair_yield(VALUE pair)
00072 {
00073 return rb_ensure(rb_yield, pair, io_close, rb_ary_entry(pair, 1));
00074 }
00075 #endif
00076
00077 #if defined HAVE_SOCKETPAIR
00078
00079 static int
00080 rsock_socketpair0(int domain, int type, int protocol, int sv[2])
00081 {
00082 int ret;
00083
00084 #ifdef SOCK_CLOEXEC
00085 static int try_sock_cloexec = 1;
00086 if (try_sock_cloexec) {
00087 ret = socketpair(domain, type|SOCK_CLOEXEC, protocol, sv);
00088 if (ret == -1 && errno == EINVAL) {
00089
00090 ret = socketpair(domain, type, protocol, sv);
00091 if (ret != -1) {
00092
00093
00094
00095
00096 try_sock_cloexec = 0;
00097 }
00098 }
00099 }
00100 else {
00101 ret = socketpair(domain, type, protocol, sv);
00102 }
00103 #else
00104 ret = socketpair(domain, type, protocol, sv);
00105 #endif
00106
00107 if (ret == -1) {
00108 return -1;
00109 }
00110
00111 rb_fd_fix_cloexec(sv[0]);
00112 rb_fd_fix_cloexec(sv[1]);
00113
00114 return ret;
00115 }
00116
00117 static int
00118 rsock_socketpair(int domain, int type, int protocol, int sv[2])
00119 {
00120 int ret;
00121
00122 ret = rsock_socketpair0(domain, type, protocol, sv);
00123 if (ret < 0 && (errno == EMFILE || errno == ENFILE)) {
00124 rb_gc();
00125 ret = rsock_socketpair0(domain, type, protocol, sv);
00126 }
00127
00128 return ret;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152 VALUE
00153 rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
00154 {
00155 VALUE domain, type, protocol;
00156 int d, t, p, sp[2];
00157 int ret;
00158 VALUE s1, s2, r;
00159
00160 rb_scan_args(argc, argv, "21", &domain, &type, &protocol);
00161 if (NIL_P(protocol))
00162 protocol = INT2FIX(0);
00163
00164 setup_domain_and_type(domain, &d, type, &t);
00165 p = NUM2INT(protocol);
00166 ret = rsock_socketpair(d, t, p, sp);
00167 if (ret < 0) {
00168 rb_sys_fail("socketpair(2)");
00169 }
00170 rb_fd_fix_cloexec(sp[0]);
00171 rb_fd_fix_cloexec(sp[1]);
00172
00173 s1 = rsock_init_sock(rb_obj_alloc(klass), sp[0]);
00174 s2 = rsock_init_sock(rb_obj_alloc(klass), sp[1]);
00175 r = rb_assoc_new(s1, s2);
00176 if (rb_block_given_p()) {
00177 return rb_ensure(pair_yield, r, io_close, s1);
00178 }
00179 return r;
00180 }
00181 #else
00182 #define rsock_sock_s_socketpair rb_f_notimplement
00183 #endif
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
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
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 static VALUE
00297 sock_connect(VALUE sock, VALUE addr)
00298 {
00299 rb_io_t *fptr;
00300 int fd, n;
00301
00302 SockAddrStringValue(addr);
00303 addr = rb_str_new4(addr);
00304 GetOpenFile(sock, fptr);
00305 fd = fptr->fd;
00306 n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr), 0);
00307 if (n < 0) {
00308 rb_sys_fail("connect(2)");
00309 }
00310
00311 return INT2FIX(n);
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 static VALUE
00357 sock_connect_nonblock(VALUE sock, VALUE addr)
00358 {
00359 rb_io_t *fptr;
00360 int n;
00361
00362 SockAddrStringValue(addr);
00363 addr = rb_str_new4(addr);
00364 GetOpenFile(sock, fptr);
00365 rb_io_set_nonblock(fptr);
00366 n = connect(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr));
00367 if (n < 0) {
00368 if (errno == EINPROGRESS)
00369 rb_mod_sys_fail(rb_mWaitWritable, "connect(2) would block");
00370 rb_sys_fail("connect(2)");
00371 }
00372
00373 return INT2FIX(n);
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
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
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 static VALUE
00463 sock_bind(VALUE sock, VALUE addr)
00464 {
00465 rb_io_t *fptr;
00466
00467 SockAddrStringValue(addr);
00468 GetOpenFile(sock, fptr);
00469 if (bind(fptr->fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_LENINT(addr)) < 0)
00470 rb_sys_fail("bind(2)");
00471
00472 return INT2FIX(0);
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
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 VALUE
00546 rsock_sock_listen(VALUE sock, VALUE log)
00547 {
00548 rb_io_t *fptr;
00549 int backlog;
00550
00551 rb_secure(4);
00552 backlog = NUM2INT(log);
00553 GetOpenFile(sock, fptr);
00554 if (listen(fptr->fd, backlog) < 0)
00555 rb_sys_fail("listen(2)");
00556
00557 return INT2FIX(0);
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
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
00659
00660
00661
00662
00663
00664
00665 static VALUE
00666 sock_recvfrom(int argc, VALUE *argv, VALUE sock)
00667 {
00668 return rsock_s_recvfrom(sock, argc, argv, RECV_SOCKET);
00669 }
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 static VALUE
00734 sock_recvfrom_nonblock(int argc, VALUE *argv, VALUE sock)
00735 {
00736 return rsock_s_recvfrom_nonblock(sock, argc, argv, RECV_SOCKET);
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 static VALUE
00754 sock_accept(VALUE sock)
00755 {
00756 rb_io_t *fptr;
00757 VALUE sock2;
00758 struct sockaddr_storage buf;
00759 socklen_t len = (socklen_t)sizeof buf;
00760
00761 GetOpenFile(sock, fptr);
00762 sock2 = rsock_s_accept(rb_cSocket,fptr->fd,(struct sockaddr*)&buf,&len);
00763
00764 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
00765 }
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
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 static VALUE
00819 sock_accept_nonblock(VALUE sock)
00820 {
00821 rb_io_t *fptr;
00822 VALUE sock2;
00823 struct sockaddr_storage buf;
00824 socklen_t len = (socklen_t)sizeof buf;
00825
00826 GetOpenFile(sock, fptr);
00827 sock2 = rsock_s_accept_nonblock(rb_cSocket, fptr, (struct sockaddr *)&buf, &len);
00828 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
00829 }
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 static VALUE
00870 sock_sysaccept(VALUE sock)
00871 {
00872 rb_io_t *fptr;
00873 VALUE sock2;
00874 struct sockaddr_storage buf;
00875 socklen_t len = (socklen_t)sizeof buf;
00876
00877 GetOpenFile(sock, fptr);
00878 sock2 = rsock_s_accept(0,fptr->fd,(struct sockaddr*)&buf,&len);
00879
00880 return rb_assoc_new(sock2, rsock_io_socket_addrinfo(sock2, (struct sockaddr*)&buf, len));
00881 }
00882
00883 #ifdef HAVE_GETHOSTNAME
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 static VALUE
00896 sock_gethostname(VALUE obj)
00897 {
00898 #ifndef HOST_NAME_MAX
00899 # define HOST_NAME_MAX 1024
00900 #endif
00901 char buf[HOST_NAME_MAX+1];
00902
00903 rb_secure(3);
00904 if (gethostname(buf, (int)sizeof buf - 1) < 0)
00905 rb_sys_fail("gethostname");
00906
00907 buf[sizeof buf - 1] = '\0';
00908 return rb_str_new2(buf);
00909 }
00910 #else
00911 #ifdef HAVE_UNAME
00912
00913 #include <sys/utsname.h>
00914
00915 static VALUE
00916 sock_gethostname(VALUE obj)
00917 {
00918 struct utsname un;
00919
00920 rb_secure(3);
00921 uname(&un);
00922 return rb_str_new2(un.nodename);
00923 }
00924 #else
00925 #define sock_gethostname rb_f_notimplement
00926 #endif
00927 #endif
00928
00929 static VALUE
00930 make_addrinfo(struct addrinfo *res0, int norevlookup)
00931 {
00932 VALUE base, ary;
00933 struct addrinfo *res;
00934
00935 if (res0 == NULL) {
00936 rb_raise(rb_eSocket, "host not found");
00937 }
00938 base = rb_ary_new();
00939 for (res = res0; res; res = res->ai_next) {
00940 ary = rsock_ipaddr(res->ai_addr, res->ai_addrlen, norevlookup);
00941 if (res->ai_canonname) {
00942 RARRAY_PTR(ary)[2] = rb_str_new2(res->ai_canonname);
00943 }
00944 rb_ary_push(ary, INT2FIX(res->ai_family));
00945 rb_ary_push(ary, INT2FIX(res->ai_socktype));
00946 rb_ary_push(ary, INT2FIX(res->ai_protocol));
00947 rb_ary_push(base, ary);
00948 }
00949 return base;
00950 }
00951
00952 static VALUE
00953 sock_sockaddr(struct sockaddr *addr, size_t len)
00954 {
00955 char *ptr;
00956
00957 switch (addr->sa_family) {
00958 case AF_INET:
00959 ptr = (char*)&((struct sockaddr_in*)addr)->sin_addr.s_addr;
00960 len = sizeof(((struct sockaddr_in*)addr)->sin_addr.s_addr);
00961 break;
00962 #ifdef AF_INET6
00963 case AF_INET6:
00964 ptr = (char*)&((struct sockaddr_in6*)addr)->sin6_addr.s6_addr;
00965 len = sizeof(((struct sockaddr_in6*)addr)->sin6_addr.s6_addr);
00966 break;
00967 #endif
00968 default:
00969 rb_raise(rb_eSocket, "unknown socket family:%d", addr->sa_family);
00970 break;
00971 }
00972 return rb_str_new(ptr, len);
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 static VALUE
00985 sock_s_gethostbyname(VALUE obj, VALUE host)
00986 {
00987 rb_secure(3);
00988 return rsock_make_hostent(host, rsock_addrinfo(host, Qnil, SOCK_STREAM, AI_CANONNAME), sock_sockaddr);
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000 static VALUE
01001 sock_s_gethostbyaddr(int argc, VALUE *argv)
01002 {
01003 VALUE addr, family;
01004 struct hostent *h;
01005 char **pch;
01006 VALUE ary, names;
01007 int t = AF_INET;
01008
01009 rb_scan_args(argc, argv, "11", &addr, &family);
01010 StringValue(addr);
01011 if (!NIL_P(family)) {
01012 t = rsock_family_arg(family);
01013 }
01014 #ifdef AF_INET6
01015 else if (RSTRING_LEN(addr) == 16) {
01016 t = AF_INET6;
01017 }
01018 #endif
01019 h = gethostbyaddr(RSTRING_PTR(addr), RSTRING_LENINT(addr), t);
01020 if (h == NULL) {
01021 #ifdef HAVE_HSTRERROR
01022 extern int h_errno;
01023 rb_raise(rb_eSocket, "%s", (char*)hstrerror(h_errno));
01024 #else
01025 rb_raise(rb_eSocket, "host not found");
01026 #endif
01027 }
01028 ary = rb_ary_new();
01029 rb_ary_push(ary, rb_str_new2(h->h_name));
01030 names = rb_ary_new();
01031 rb_ary_push(ary, names);
01032 if (h->h_aliases != NULL) {
01033 for (pch = h->h_aliases; *pch; pch++) {
01034 rb_ary_push(names, rb_str_new2(*pch));
01035 }
01036 }
01037 rb_ary_push(ary, INT2NUM(h->h_addrtype));
01038 #ifdef h_addr
01039 for (pch = h->h_addr_list; *pch; pch++) {
01040 rb_ary_push(ary, rb_str_new(*pch, h->h_length));
01041 }
01042 #else
01043 rb_ary_push(ary, rb_str_new(h->h_addr, h->h_length));
01044 #endif
01045
01046 return ary;
01047 }
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062 static VALUE
01063 sock_s_getservbyname(int argc, VALUE *argv)
01064 {
01065 VALUE service, proto;
01066 struct servent *sp;
01067 long port;
01068 const char *servicename, *protoname = "tcp";
01069
01070 rb_scan_args(argc, argv, "11", &service, &proto);
01071 StringValue(service);
01072 if (!NIL_P(proto)) StringValue(proto);
01073 servicename = StringValueCStr(service);
01074 if (!NIL_P(proto)) protoname = StringValueCStr(proto);
01075 sp = getservbyname(servicename, protoname);
01076 if (sp) {
01077 port = ntohs(sp->s_port);
01078 }
01079 else {
01080 char *end;
01081
01082 port = STRTOUL(servicename, &end, 0);
01083 if (*end != '\0') {
01084 rb_raise(rb_eSocket, "no such service %s/%s", servicename, protoname);
01085 }
01086 }
01087 return INT2FIX(port);
01088 }
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 static VALUE
01104 sock_s_getservbyport(int argc, VALUE *argv)
01105 {
01106 VALUE port, proto;
01107 struct servent *sp;
01108 long portnum;
01109 const char *protoname = "tcp";
01110
01111 rb_scan_args(argc, argv, "11", &port, &proto);
01112 portnum = NUM2LONG(port);
01113 if (portnum != (uint16_t)portnum) {
01114 const char *s = portnum > 0 ? "big" : "small";
01115 rb_raise(rb_eRangeError, "integer %ld too %s to convert into `int16_t'", portnum, s);
01116 }
01117 if (!NIL_P(proto)) protoname = StringValueCStr(proto);
01118
01119 sp = getservbyport((int)htons((uint16_t)portnum), protoname);
01120 if (!sp) {
01121 rb_raise(rb_eSocket, "no such service for port %d/%s", (int)portnum, protoname);
01122 }
01123 return rb_tainted_str_new2(sp->s_name);
01124 }
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 static VALUE
01159 sock_s_getaddrinfo(int argc, VALUE *argv)
01160 {
01161 VALUE host, port, family, socktype, protocol, flags, ret, revlookup;
01162 struct addrinfo hints, *res;
01163 int norevlookup;
01164
01165 rb_scan_args(argc, argv, "25", &host, &port, &family, &socktype, &protocol, &flags, &revlookup);
01166
01167 MEMZERO(&hints, struct addrinfo, 1);
01168 hints.ai_family = NIL_P(family) ? PF_UNSPEC : rsock_family_arg(family);
01169
01170 if (!NIL_P(socktype)) {
01171 hints.ai_socktype = rsock_socktype_arg(socktype);
01172 }
01173 if (!NIL_P(protocol)) {
01174 hints.ai_protocol = NUM2INT(protocol);
01175 }
01176 if (!NIL_P(flags)) {
01177 hints.ai_flags = NUM2INT(flags);
01178 }
01179 if (NIL_P(revlookup) || !rsock_revlookup_flag(revlookup, &norevlookup)) {
01180 norevlookup = rsock_do_not_reverse_lookup;
01181 }
01182 res = rsock_getaddrinfo(host, port, &hints, 0);
01183
01184 ret = make_addrinfo(res, norevlookup);
01185 freeaddrinfo(res);
01186 return ret;
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211 static VALUE
01212 sock_s_getnameinfo(int argc, VALUE *argv)
01213 {
01214 VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags, tmp;
01215 char *hptr, *pptr;
01216 char hbuf[1024], pbuf[1024];
01217 int fl;
01218 struct addrinfo hints, *res = NULL, *r;
01219 int error, saved_errno;
01220 struct sockaddr_storage ss;
01221 struct sockaddr *sap;
01222 socklen_t salen;
01223
01224 sa = flags = Qnil;
01225 rb_scan_args(argc, argv, "11", &sa, &flags);
01226
01227 fl = 0;
01228 if (!NIL_P(flags)) {
01229 fl = NUM2INT(flags);
01230 }
01231 tmp = rb_check_sockaddr_string_type(sa);
01232 if (!NIL_P(tmp)) {
01233 sa = tmp;
01234 if (sizeof(ss) < (size_t)RSTRING_LEN(sa)) {
01235 rb_raise(rb_eTypeError, "sockaddr length too big");
01236 }
01237 memcpy(&ss, RSTRING_PTR(sa), RSTRING_LEN(sa));
01238 if ((size_t)RSTRING_LEN(sa) != SS_LEN(&ss)) {
01239 rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
01240 }
01241 sap = (struct sockaddr*)&ss;
01242 salen = RSTRING_LEN(sa);
01243 goto call_nameinfo;
01244 }
01245 tmp = rb_check_array_type(sa);
01246 if (!NIL_P(tmp)) {
01247 sa = tmp;
01248 MEMZERO(&hints, struct addrinfo, 1);
01249 if (RARRAY_LEN(sa) == 3) {
01250 af = RARRAY_PTR(sa)[0];
01251 port = RARRAY_PTR(sa)[1];
01252 host = RARRAY_PTR(sa)[2];
01253 }
01254 else if (RARRAY_LEN(sa) >= 4) {
01255 af = RARRAY_PTR(sa)[0];
01256 port = RARRAY_PTR(sa)[1];
01257 host = RARRAY_PTR(sa)[3];
01258 if (NIL_P(host)) {
01259 host = RARRAY_PTR(sa)[2];
01260 }
01261 else {
01262
01263
01264
01265
01266 #ifdef AI_NUMERICHOST
01267 hints.ai_flags |= AI_NUMERICHOST;
01268 #endif
01269 }
01270 }
01271 else {
01272 rb_raise(rb_eArgError, "array size should be 3 or 4, %ld given",
01273 RARRAY_LEN(sa));
01274 }
01275
01276 if (NIL_P(host)) {
01277 hptr = NULL;
01278 }
01279 else {
01280 strncpy(hbuf, StringValuePtr(host), sizeof(hbuf));
01281 hbuf[sizeof(hbuf) - 1] = '\0';
01282 hptr = hbuf;
01283 }
01284
01285 if (NIL_P(port)) {
01286 strcpy(pbuf, "0");
01287 pptr = NULL;
01288 }
01289 else if (FIXNUM_P(port)) {
01290 snprintf(pbuf, sizeof(pbuf), "%ld", NUM2LONG(port));
01291 pptr = pbuf;
01292 }
01293 else {
01294 strncpy(pbuf, StringValuePtr(port), sizeof(pbuf));
01295 pbuf[sizeof(pbuf) - 1] = '\0';
01296 pptr = pbuf;
01297 }
01298 hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
01299
01300 hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
01301 error = rb_getaddrinfo(hptr, pptr, &hints, &res);
01302 if (error) goto error_exit_addr;
01303 sap = res->ai_addr;
01304 salen = res->ai_addrlen;
01305 }
01306 else {
01307 rb_raise(rb_eTypeError, "expecting String or Array");
01308 }
01309
01310 call_nameinfo:
01311 error = rb_getnameinfo(sap, salen, hbuf, sizeof(hbuf),
01312 pbuf, sizeof(pbuf), fl);
01313 if (error) goto error_exit_name;
01314 if (res) {
01315 for (r = res->ai_next; r; r = r->ai_next) {
01316 char hbuf2[1024], pbuf2[1024];
01317
01318 sap = r->ai_addr;
01319 salen = r->ai_addrlen;
01320 error = rb_getnameinfo(sap, salen, hbuf2, sizeof(hbuf2),
01321 pbuf2, sizeof(pbuf2), fl);
01322 if (error) goto error_exit_name;
01323 if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
01324 freeaddrinfo(res);
01325 rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
01326 }
01327 }
01328 freeaddrinfo(res);
01329 }
01330 return rb_assoc_new(rb_str_new2(hbuf), rb_str_new2(pbuf));
01331
01332 error_exit_addr:
01333 saved_errno = errno;
01334 if (res) freeaddrinfo(res);
01335 errno = saved_errno;
01336 rsock_raise_socket_error("getaddrinfo", error);
01337
01338 error_exit_name:
01339 saved_errno = errno;
01340 if (res) freeaddrinfo(res);
01341 errno = saved_errno;
01342 rsock_raise_socket_error("getnameinfo", error);
01343
01344 UNREACHABLE;
01345 }
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361 static VALUE
01362 sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
01363 {
01364 struct addrinfo *res = rsock_addrinfo(host, port, 0, 0);
01365 VALUE addr = rb_str_new((char*)res->ai_addr, res->ai_addrlen);
01366
01367 freeaddrinfo(res);
01368 OBJ_INFECT(addr, port);
01369 OBJ_INFECT(addr, host);
01370
01371 return addr;
01372 }
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387 static VALUE
01388 sock_s_unpack_sockaddr_in(VALUE self, VALUE addr)
01389 {
01390 struct sockaddr_in * sockaddr;
01391 VALUE host;
01392
01393 sockaddr = (struct sockaddr_in*)SockAddrStringValuePtr(addr);
01394 if (RSTRING_LEN(addr) <
01395 (char*)&((struct sockaddr *)sockaddr)->sa_family +
01396 sizeof(((struct sockaddr *)sockaddr)->sa_family) -
01397 (char*)sockaddr)
01398 rb_raise(rb_eArgError, "too short sockaddr");
01399 if (((struct sockaddr *)sockaddr)->sa_family != AF_INET
01400 #ifdef INET6
01401 && ((struct sockaddr *)sockaddr)->sa_family != AF_INET6
01402 #endif
01403 ) {
01404 #ifdef INET6
01405 rb_raise(rb_eArgError, "not an AF_INET/AF_INET6 sockaddr");
01406 #else
01407 rb_raise(rb_eArgError, "not an AF_INET sockaddr");
01408 #endif
01409 }
01410 host = rsock_make_ipaddr((struct sockaddr*)sockaddr, RSTRING_LEN(addr));
01411 OBJ_INFECT(host, addr);
01412 return rb_assoc_new(INT2NUM(ntohs(sockaddr->sin_port)), host);
01413 }
01414
01415 #ifdef HAVE_SYS_UN_H
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427 static VALUE
01428 sock_s_pack_sockaddr_un(VALUE self, VALUE path)
01429 {
01430 struct sockaddr_un sockaddr;
01431 VALUE addr;
01432
01433 StringValue(path);
01434 MEMZERO(&sockaddr, struct sockaddr_un, 1);
01435 sockaddr.sun_family = AF_UNIX;
01436 if (sizeof(sockaddr.sun_path) < (size_t)RSTRING_LEN(path)) {
01437 rb_raise(rb_eArgError, "too long unix socket path (%"PRIuSIZE" bytes given but %"PRIuSIZE" bytes max)",
01438 (size_t)RSTRING_LEN(path), sizeof(sockaddr.sun_path));
01439 }
01440 memcpy(sockaddr.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
01441 addr = rb_str_new((char*)&sockaddr, rsock_unix_sockaddr_len(path));
01442 OBJ_INFECT(addr, path);
01443
01444 return addr;
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459 static VALUE
01460 sock_s_unpack_sockaddr_un(VALUE self, VALUE addr)
01461 {
01462 struct sockaddr_un * sockaddr;
01463 VALUE path;
01464
01465 sockaddr = (struct sockaddr_un*)SockAddrStringValuePtr(addr);
01466 if (RSTRING_LEN(addr) <
01467 (char*)&((struct sockaddr *)sockaddr)->sa_family +
01468 sizeof(((struct sockaddr *)sockaddr)->sa_family) -
01469 (char*)sockaddr)
01470 rb_raise(rb_eArgError, "too short sockaddr");
01471 if (((struct sockaddr *)sockaddr)->sa_family != AF_UNIX) {
01472 rb_raise(rb_eArgError, "not an AF_UNIX sockaddr");
01473 }
01474 if (sizeof(struct sockaddr_un) < (size_t)RSTRING_LEN(addr)) {
01475 rb_raise(rb_eTypeError, "too long sockaddr_un - %ld longer than %d",
01476 RSTRING_LEN(addr), (int)sizeof(struct sockaddr_un));
01477 }
01478 path = rsock_unixpath_str(sockaddr, RSTRING_LENINT(addr));
01479 OBJ_INFECT(path, addr);
01480 return path;
01481 }
01482 #endif
01483
01484 #if defined(HAVE_GETIFADDRS) || defined(SIOCGLIFCONF) || defined(SIOCGIFCONF) || defined(_WIN32)
01485 static VALUE
01486 sockaddr_obj(struct sockaddr *addr)
01487 {
01488 socklen_t len;
01489 #if defined(AF_INET6) && defined(__KAME__)
01490 struct sockaddr_in6 addr6;
01491 #endif
01492
01493 if (addr == NULL)
01494 return Qnil;
01495
01496 switch (addr->sa_family) {
01497 case AF_INET:
01498 len = (socklen_t)sizeof(struct sockaddr_in);
01499 break;
01500
01501 #ifdef AF_INET6
01502 case AF_INET6:
01503 len = (socklen_t)sizeof(struct sockaddr_in6);
01504 # ifdef __KAME__
01505
01506
01507
01508 memcpy(&addr6, addr, len);
01509 addr = (struct sockaddr *)&addr6;
01510 if (IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) &&
01511 addr6.sin6_scope_id == 0 &&
01512 (addr6.sin6_addr.s6_addr[2] || addr6.sin6_addr.s6_addr[3])) {
01513 addr6.sin6_scope_id = (addr6.sin6_addr.s6_addr[2] << 8) | addr6.sin6_addr.s6_addr[3];
01514 addr6.sin6_addr.s6_addr[2] = 0;
01515 addr6.sin6_addr.s6_addr[3] = 0;
01516 }
01517 # endif
01518 break;
01519 #endif
01520
01521 #ifdef HAVE_SYS_UN_H
01522 case AF_UNIX:
01523 len = (socklen_t)sizeof(struct sockaddr_un);
01524 break;
01525 #endif
01526
01527 default:
01528 len = (socklen_t)sizeof(struct sockaddr_in);
01529 break;
01530 }
01531 #ifdef SA_LEN
01532 if (len < (socklen_t)SA_LEN(addr))
01533 len = (socklen_t)SA_LEN(addr);
01534 #endif
01535
01536 return rsock_addrinfo_new(addr, len, addr->sa_family, 0, 0, Qnil, Qnil);
01537 }
01538 #endif
01539
01540 #if defined(HAVE_GETIFADDRS) || (defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)) || defined(SIOCGIFCONF) || defined(_WIN32)
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556 static VALUE
01557 socket_s_ip_address_list(VALUE self)
01558 {
01559 #if defined(HAVE_GETIFADDRS)
01560 struct ifaddrs *ifp = NULL;
01561 struct ifaddrs *p;
01562 int ret;
01563 VALUE list;
01564
01565 ret = getifaddrs(&ifp);
01566 if (ret == -1) {
01567 rb_sys_fail("getifaddrs");
01568 }
01569
01570 list = rb_ary_new();
01571 for (p = ifp; p; p = p->ifa_next) {
01572 if (p->ifa_addr != NULL && IS_IP_FAMILY(p->ifa_addr->sa_family)) {
01573 rb_ary_push(list, sockaddr_obj(p->ifa_addr));
01574 }
01575 }
01576
01577 freeifaddrs(ifp);
01578
01579 return list;
01580 #elif defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && !defined(__hpux)
01581
01582
01583 int fd = -1;
01584 int ret;
01585 struct lifnum ln;
01586 struct lifconf lc;
01587 char *reason = NULL;
01588 int save_errno;
01589 int i;
01590 VALUE list = Qnil;
01591
01592 lc.lifc_buf = NULL;
01593
01594 fd = socket(AF_INET, SOCK_DGRAM, 0);
01595 if (fd == -1)
01596 rb_sys_fail("socket");
01597
01598 memset(&ln, 0, sizeof(ln));
01599 ln.lifn_family = AF_UNSPEC;
01600
01601 ret = ioctl(fd, SIOCGLIFNUM, &ln);
01602 if (ret == -1) {
01603 reason = "SIOCGLIFNUM";
01604 goto finish;
01605 }
01606
01607 memset(&lc, 0, sizeof(lc));
01608 lc.lifc_family = AF_UNSPEC;
01609 lc.lifc_flags = 0;
01610 lc.lifc_len = sizeof(struct lifreq) * ln.lifn_count;
01611 lc.lifc_req = xmalloc(lc.lifc_len);
01612
01613 ret = ioctl(fd, SIOCGLIFCONF, &lc);
01614 if (ret == -1) {
01615 reason = "SIOCGLIFCONF";
01616 goto finish;
01617 }
01618
01619 list = rb_ary_new();
01620 for (i = 0; i < ln.lifn_count; i++) {
01621 struct lifreq *req = &lc.lifc_req[i];
01622 if (IS_IP_FAMILY(req->lifr_addr.ss_family)) {
01623 if (req->lifr_addr.ss_family == AF_INET6 &&
01624 IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_addr) &&
01625 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id == 0) {
01626 struct lifreq req2;
01627 memcpy(req2.lifr_name, req->lifr_name, LIFNAMSIZ);
01628 ret = ioctl(fd, SIOCGLIFINDEX, &req2);
01629 if (ret == -1) {
01630 reason = "SIOCGLIFINDEX";
01631 goto finish;
01632 }
01633 ((struct sockaddr_in6 *)(&req->lifr_addr))->sin6_scope_id = req2.lifr_index;
01634 }
01635 rb_ary_push(list, sockaddr_obj((struct sockaddr *)&req->lifr_addr));
01636 }
01637 }
01638
01639 finish:
01640 save_errno = errno;
01641 if (lc.lifc_buf != NULL)
01642 xfree(lc.lifc_req);
01643 if (fd != -1)
01644 close(fd);
01645 errno = save_errno;
01646
01647 if (reason)
01648 rb_sys_fail(reason);
01649 return list;
01650
01651 #elif defined(SIOCGIFCONF)
01652 int fd = -1;
01653 int ret;
01654 #define EXTRA_SPACE (sizeof(struct ifconf) + sizeof(struct sockaddr_storage))
01655 char initbuf[4096+EXTRA_SPACE];
01656 char *buf = initbuf;
01657 int bufsize;
01658 struct ifconf conf;
01659 struct ifreq *req;
01660 VALUE list = Qnil;
01661 const char *reason = NULL;
01662 int save_errno;
01663
01664 fd = socket(AF_INET, SOCK_DGRAM, 0);
01665 if (fd == -1)
01666 rb_sys_fail("socket");
01667
01668 bufsize = sizeof(initbuf);
01669 buf = initbuf;
01670
01671 retry:
01672 conf.ifc_len = bufsize;
01673 conf.ifc_req = (struct ifreq *)buf;
01674
01675
01676
01677 ret = ioctl(fd, SIOCGIFCONF, &conf);
01678 if (ret == -1) {
01679 reason = "SIOCGIFCONF";
01680 goto finish;
01681 }
01682
01683
01684
01685 if (bufsize - EXTRA_SPACE < conf.ifc_len) {
01686 if (bufsize < conf.ifc_len) {
01687
01688 bufsize = conf.ifc_len + EXTRA_SPACE;
01689 }
01690 else {
01691 bufsize = bufsize << 1;
01692 }
01693 if (buf == initbuf)
01694 buf = NULL;
01695 buf = xrealloc(buf, bufsize);
01696 goto retry;
01697 }
01698
01699 close(fd);
01700 fd = -1;
01701
01702 list = rb_ary_new();
01703 req = conf.ifc_req;
01704 while ((char*)req < (char*)conf.ifc_req + conf.ifc_len) {
01705 struct sockaddr *addr = &req->ifr_addr;
01706 if (IS_IP_FAMILY(addr->sa_family)) {
01707 rb_ary_push(list, sockaddr_obj(addr));
01708 }
01709 #ifdef HAVE_SA_LEN
01710 # ifndef _SIZEOF_ADDR_IFREQ
01711 # define _SIZEOF_ADDR_IFREQ(r) \
01712 (sizeof(struct ifreq) + \
01713 (sizeof(struct sockaddr) < (r).ifr_addr.sa_len ? \
01714 (r).ifr_addr.sa_len - sizeof(struct sockaddr) : \
01715 0))
01716 # endif
01717 req = (struct ifreq *)((char*)req + _SIZEOF_ADDR_IFREQ(*req));
01718 #else
01719 req = (struct ifreq *)((char*)req + sizeof(struct ifreq));
01720 #endif
01721 }
01722
01723 finish:
01724
01725 save_errno = errno;
01726 if (buf != initbuf)
01727 xfree(buf);
01728 if (fd != -1)
01729 close(fd);
01730 errno = save_errno;
01731
01732 if (reason)
01733 rb_sys_fail(reason);
01734 return list;
01735
01736 #undef EXTRA_SPACE
01737 #elif defined(_WIN32)
01738 typedef struct ip_adapter_unicast_address_st {
01739 unsigned LONG_LONG dummy0;
01740 struct ip_adapter_unicast_address_st *Next;
01741 struct {
01742 struct sockaddr *lpSockaddr;
01743 int iSockaddrLength;
01744 } Address;
01745 int dummy1;
01746 int dummy2;
01747 int dummy3;
01748 long dummy4;
01749 long dummy5;
01750 long dummy6;
01751 } ip_adapter_unicast_address_t;
01752 typedef struct ip_adapter_anycast_address_st {
01753 unsigned LONG_LONG dummy0;
01754 struct ip_adapter_anycast_address_st *Next;
01755 struct {
01756 struct sockaddr *lpSockaddr;
01757 int iSockaddrLength;
01758 } Address;
01759 } ip_adapter_anycast_address_t;
01760 typedef struct ip_adapter_addresses_st {
01761 unsigned LONG_LONG dummy0;
01762 struct ip_adapter_addresses_st *Next;
01763 void *dummy1;
01764 ip_adapter_unicast_address_t *FirstUnicastAddress;
01765 ip_adapter_anycast_address_t *FirstAnycastAddress;
01766 void *dummy2;
01767 void *dummy3;
01768 void *dummy4;
01769 void *dummy5;
01770 void *dummy6;
01771 BYTE dummy7[8];
01772 DWORD dummy8;
01773 DWORD dummy9;
01774 DWORD dummy10;
01775 DWORD IfType;
01776 int OperStatus;
01777 DWORD dummy12;
01778 DWORD dummy13[16];
01779 void *dummy14;
01780 } ip_adapter_addresses_t;
01781 typedef ULONG (WINAPI *GetAdaptersAddresses_t)(ULONG, ULONG, PVOID, ip_adapter_addresses_t *, PULONG);
01782 HMODULE h;
01783 GetAdaptersAddresses_t pGetAdaptersAddresses;
01784 ULONG len;
01785 DWORD ret;
01786 ip_adapter_addresses_t *adapters;
01787 VALUE list;
01788
01789 h = LoadLibrary("iphlpapi.dll");
01790 if (!h)
01791 rb_notimplement();
01792 pGetAdaptersAddresses = (GetAdaptersAddresses_t)GetProcAddress(h, "GetAdaptersAddresses");
01793 if (!pGetAdaptersAddresses) {
01794 FreeLibrary(h);
01795 rb_notimplement();
01796 }
01797
01798 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &len);
01799 if (ret != ERROR_SUCCESS && ret != ERROR_BUFFER_OVERFLOW) {
01800 errno = rb_w32_map_errno(ret);
01801 FreeLibrary(h);
01802 rb_sys_fail("GetAdaptersAddresses");
01803 }
01804 adapters = (ip_adapter_addresses_t *)ALLOCA_N(BYTE, len);
01805 ret = pGetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &len);
01806 if (ret != ERROR_SUCCESS) {
01807 errno = rb_w32_map_errno(ret);
01808 FreeLibrary(h);
01809 rb_sys_fail("GetAdaptersAddresses");
01810 }
01811
01812 list = rb_ary_new();
01813 for (; adapters; adapters = adapters->Next) {
01814 ip_adapter_unicast_address_t *uni;
01815 ip_adapter_anycast_address_t *any;
01816 if (adapters->OperStatus != 1)
01817 continue;
01818 for (uni = adapters->FirstUnicastAddress; uni; uni = uni->Next) {
01819 #ifndef INET6
01820 if (uni->Address.lpSockaddr->sa_family == AF_INET)
01821 #else
01822 if (IS_IP_FAMILY(uni->Address.lpSockaddr->sa_family))
01823 #endif
01824 rb_ary_push(list, sockaddr_obj(uni->Address.lpSockaddr));
01825 }
01826 for (any = adapters->FirstAnycastAddress; any; any = any->Next) {
01827 #ifndef INET6
01828 if (any->Address.lpSockaddr->sa_family == AF_INET)
01829 #else
01830 if (IS_IP_FAMILY(any->Address.lpSockaddr->sa_family))
01831 #endif
01832 rb_ary_push(list, sockaddr_obj(any->Address.lpSockaddr));
01833 }
01834 }
01835
01836 FreeLibrary(h);
01837 return list;
01838 #endif
01839 }
01840 #else
01841 #define socket_s_ip_address_list rb_f_notimplement
01842 #endif
01843
01844 void
01845 Init_socket()
01846 {
01847 rsock_init_basicsocket();
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961
01962
01963
01964 rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
01965
01966 rsock_init_socket_init();
01967
01968 rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
01969 rb_define_method(rb_cSocket, "connect", sock_connect, 1);
01970 rb_define_method(rb_cSocket, "connect_nonblock", sock_connect_nonblock, 1);
01971 rb_define_method(rb_cSocket, "bind", sock_bind, 1);
01972 rb_define_method(rb_cSocket, "listen", rsock_sock_listen, 1);
01973 rb_define_method(rb_cSocket, "accept", sock_accept, 0);
01974 rb_define_method(rb_cSocket, "accept_nonblock", sock_accept_nonblock, 0);
01975 rb_define_method(rb_cSocket, "sysaccept", sock_sysaccept, 0);
01976
01977 rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
01978 rb_define_method(rb_cSocket, "recvfrom_nonblock", sock_recvfrom_nonblock, -1);
01979
01980 rb_define_singleton_method(rb_cSocket, "socketpair", rsock_sock_s_socketpair, -1);
01981 rb_define_singleton_method(rb_cSocket, "pair", rsock_sock_s_socketpair, -1);
01982 rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
01983 rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
01984 rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
01985 rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyname, -1);
01986 rb_define_singleton_method(rb_cSocket, "getservbyport", sock_s_getservbyport, -1);
01987 rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
01988 rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
01989 rb_define_singleton_method(rb_cSocket, "sockaddr_in", sock_s_pack_sockaddr_in, 2);
01990 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_in", sock_s_pack_sockaddr_in, 2);
01991 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_in", sock_s_unpack_sockaddr_in, 1);
01992 #ifdef HAVE_SYS_UN_H
01993 rb_define_singleton_method(rb_cSocket, "sockaddr_un", sock_s_pack_sockaddr_un, 1);
01994 rb_define_singleton_method(rb_cSocket, "pack_sockaddr_un", sock_s_pack_sockaddr_un, 1);
01995 rb_define_singleton_method(rb_cSocket, "unpack_sockaddr_un", sock_s_unpack_sockaddr_un, 1);
01996 #endif
01997
01998 rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0);
01999 }
02000