Ruby  2.1.10p492(2016-04-01revision54464)
option.c
Go to the documentation of this file.
1 #include "rubysocket.h"
2 
4 
5 static VALUE
6 constant_to_sym(int constant, ID (*intern_const)(int))
7 {
8  ID name = intern_const(constant);
9  if (name) {
10  return ID2SYM(name);
11  }
12 
13  return INT2NUM(constant);
14 }
15 
16 static VALUE
17 optname_to_sym(int level, int optname)
18 {
19  switch (level) {
20  case SOL_SOCKET:
21  return constant_to_sym(optname, rsock_intern_so_optname);
22  case IPPROTO_IP:
23  return constant_to_sym(optname, rsock_intern_ip_optname);
24 #ifdef IPPROTO_IPV6
25  case IPPROTO_IPV6:
26  return constant_to_sym(optname, rsock_intern_ipv6_optname);
27 #endif
28  case IPPROTO_TCP:
29  return constant_to_sym(optname, rsock_intern_tcp_optname);
30  case IPPROTO_UDP:
31  return constant_to_sym(optname, rsock_intern_udp_optname);
32  default:
33  return INT2NUM(optname);
34  }
35 }
36 
37 /*
38  * call-seq:
39  * Socket::Option.new(family, level, optname, data) => sockopt
40  *
41  * Returns a new Socket::Option object.
42  *
43  * sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
44  * p sockopt #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
45  *
46  */
47 static VALUE
48 sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE data)
49 {
50  int family = rsock_family_arg(vfamily);
51  int level = rsock_level_arg(family, vlevel);
52  int optname = rsock_optname_arg(family, level, voptname);
53  StringValue(data);
54  rb_ivar_set(self, rb_intern("family"), INT2NUM(family));
55  rb_ivar_set(self, rb_intern("level"), INT2NUM(level));
56  rb_ivar_set(self, rb_intern("optname"), INT2NUM(optname));
57  rb_ivar_set(self, rb_intern("data"), data);
58  return self;
59 }
60 
61 VALUE
62 rsock_sockopt_new(int family, int level, int optname, VALUE data)
63 {
65  StringValue(data);
66  sockopt_initialize((VALUE)obj, INT2NUM(family), INT2NUM(level), INT2NUM(optname), data);
67  return (VALUE)obj;
68 }
69 
70 /*
71  * call-seq:
72  * sockopt.family => integer
73  *
74  * returns the socket family as an integer.
75  *
76  * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).family
77  * #=> 10
78  */
79 static VALUE
81 {
82  return rb_attr_get(self, rb_intern("family"));
83 }
84 
85 static int
87 {
88  return NUM2INT(rb_attr_get(self, rb_intern("level")));
89 }
90 
91 /*
92  * call-seq:
93  * sockopt.level => integer
94  *
95  * returns the socket level as an integer.
96  *
97  * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).level
98  * #=> 41
99  */
100 static VALUE
102 {
103  return INT2NUM(sockopt_level(self));
104 }
105 
106 static int
108 {
109  return NUM2INT(rb_attr_get(self, rb_intern("optname")));
110 }
111 
112 /*
113  * call-seq:
114  * sockopt.optname => integer
115  *
116  * returns the socket option name as an integer.
117  *
118  * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).optname
119  * #=> 2
120  */
121 static VALUE
123 {
124  return INT2NUM(sockopt_optname(self));
125 }
126 
127 /*
128  * call-seq:
129  * sockopt.data => string
130  * sockopt.to_s => string
131  *
132  * returns the socket option data as a string.
133  *
134  * p Socket::Option.new(:INET6, :IPV6, :RECVPKTINFO, [1].pack("i!")).data
135  * #=> "\x01\x00\x00\x00"
136  */
137 static VALUE
139 {
140  VALUE v = rb_attr_get(self, rb_intern("data"));
141  StringValue(v);
142  return v;
143 }
144 
145 /*
146  * call-seq:
147  * Socket::Option.byte(family, level, optname, integer) => sockopt
148  *
149  * Creates a new Socket::Option object which contains a byte as data.
150  *
151  * The size and endian is dependent on the platform.
152  *
153  * p Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
154  * #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
155  */
156 static VALUE
157 sockopt_s_byte(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
158 {
159  int family = rsock_family_arg(vfamily);
160  int level = rsock_level_arg(family, vlevel);
161  int optname = rsock_optname_arg(family, level, voptname);
162  unsigned char i = (unsigned char)NUM2CHR(vint);
163  return rsock_sockopt_new(family, level, optname, rb_str_new((char*)&i, sizeof(i)));
164 }
165 
166 /*
167  * call-seq:
168  * sockopt.byte => integer
169  *
170  * Returns the data in _sockopt_ as an byte.
171  *
172  * The size and endian is dependent on the platform.
173  *
174  * sockopt = Socket::Option.byte(:INET, :SOCKET, :KEEPALIVE, 1)
175  * p sockopt.byte => 1
176  */
177 static VALUE
179 {
180  unsigned char i;
181  VALUE data = sockopt_data(self);
182  StringValue(data);
183  if (RSTRING_LEN(data) != sizeof(i))
184  rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld",
185  (int)sizeof(i), (long)RSTRING_LEN(data));
186  return CHR2FIX(*RSTRING_PTR(data));
187 }
188 
189 /*
190  * call-seq:
191  * Socket::Option.int(family, level, optname, integer) => sockopt
192  *
193  * Creates a new Socket::Option object which contains an int as data.
194  *
195  * The size and endian is dependent on the platform.
196  *
197  * p Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
198  * #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
199  */
200 static VALUE
201 sockopt_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
202 {
203  int family = rsock_family_arg(vfamily);
204  int level = rsock_level_arg(family, vlevel);
205  int optname = rsock_optname_arg(family, level, voptname);
206  int i = NUM2INT(vint);
207  return rsock_sockopt_new(family, level, optname, rb_str_new((char*)&i, sizeof(i)));
208 }
209 
210 /*
211  * call-seq:
212  * sockopt.int => integer
213  *
214  * Returns the data in _sockopt_ as an int.
215  *
216  * The size and endian is dependent on the platform.
217  *
218  * sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
219  * p sockopt.int => 1
220  */
221 static VALUE
223 {
224  int i;
225  VALUE data = sockopt_data(self);
226  StringValue(data);
227  if (RSTRING_LEN(data) != sizeof(int))
228  rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld",
229  (int)sizeof(int), (long)RSTRING_LEN(data));
230  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
231  return INT2NUM(i);
232 }
233 
234 /*
235  * call-seq:
236  * Socket::Option.bool(family, level, optname, bool) => sockopt
237  *
238  * Creates a new Socket::Option object which contains boolean as data.
239  * Actually 0 or 1 as int is used.
240  *
241  * p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, true)
242  * #=> #<Socket::Option: INET SOCKET KEEPALIVE 1>
243  *
244  * p Socket::Option.bool(:INET, :SOCKET, :KEEPALIVE, false)
245  * #=> #<Socket::Option: AF_INET SOCKET KEEPALIVE 0>
246  *
247  */
248 static VALUE
249 sockopt_s_bool(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vbool)
250 {
251  int family = rsock_family_arg(vfamily);
252  int level = rsock_level_arg(family, vlevel);
253  int optname = rsock_optname_arg(family, level, voptname);
254  int i = RTEST(vbool) ? 1 : 0;
255  return rsock_sockopt_new(family, level, optname, rb_str_new((char*)&i, sizeof(i)));
256 }
257 
258 /*
259  * call-seq:
260  * sockopt.bool => true or false
261  *
262  * Returns the data in _sockopt_ as an boolean value.
263  *
264  * sockopt = Socket::Option.int(:INET, :SOCKET, :KEEPALIVE, 1)
265  * p sockopt.bool => true
266  */
267 static VALUE
269 {
270  int i;
271  long len;
272  VALUE data = sockopt_data(self);
273  StringValue(data);
274  len = RSTRING_LEN(data);
275  if (len == 1) {
276  return *RSTRING_PTR(data) == 0 ? Qfalse : Qtrue;
277  }
278  if (len != sizeof(int))
279  rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld",
280  (int)sizeof(int), (long)len);
281  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
282  return i == 0 ? Qfalse : Qtrue;
283 }
284 
285 /*
286  * call-seq:
287  * Socket::Option.linger(onoff, secs) => sockopt
288  *
289  * Creates a new Socket::Option object for SOL_SOCKET/SO_LINGER.
290  *
291  * _onoff_ should be an integer or a boolean.
292  *
293  * _secs_ should be the number of seconds.
294  *
295  * p Socket::Option.linger(true, 10)
296  * #=> #<Socket::Option: UNSPEC SOCKET LINGER on 10sec>
297  *
298  */
299 static VALUE
301 {
302  VALUE tmp;
303  struct linger l;
304  memset(&l, 0, sizeof(l));
305  if (!NIL_P(tmp = rb_check_to_integer(vonoff, "to_int")))
306  l.l_onoff = NUM2INT(tmp);
307  else
308  l.l_onoff = RTEST(vonoff) ? 1 : 0;
309  l.l_linger = NUM2INT(vsecs);
310  return rsock_sockopt_new(AF_UNSPEC, SOL_SOCKET, SO_LINGER, rb_str_new((char*)&l, sizeof(l)));
311 }
312 
313 /*
314  * call-seq:
315  * sockopt.linger => [bool, seconds]
316  *
317  * Returns the linger data in _sockopt_ as a pair of boolean and integer.
318  *
319  * sockopt = Socket::Option.linger(true, 10)
320  * p sockopt.linger => [true, 10]
321  */
322 static VALUE
324 {
325  int level = sockopt_level(self);
326  int optname = sockopt_optname(self);
327  VALUE data = sockopt_data(self);
328  struct linger l;
329  VALUE vonoff, vsecs;
330 
331  if (level != SOL_SOCKET || optname != SO_LINGER)
332  rb_raise(rb_eTypeError, "linger socket option expected");
333  if (RSTRING_LEN(data) != sizeof(l))
334  rb_raise(rb_eTypeError, "size differ. expected as sizeof(struct linger)=%d but %ld",
335  (int)sizeof(struct linger), (long)RSTRING_LEN(data));
336  memcpy((char*)&l, RSTRING_PTR(data), sizeof(struct linger));
337  switch (l.l_onoff) {
338  case 0: vonoff = Qfalse; break;
339  case 1: vonoff = Qtrue; break;
340  default: vonoff = INT2NUM(l.l_onoff); break;
341  }
342  vsecs = INT2NUM(l.l_linger);
343  return rb_assoc_new(vonoff, vsecs);
344 }
345 
346 /*
347  * call-seq:
348  * Socket::Option.ipv4_multicast_loop(integer) => sockopt
349  *
350  * Creates a new Socket::Option object for IP_MULTICAST_LOOP.
351  *
352  * The size is dependent on the platform.
353  *
354  * sockopt = Socket::Option.int(:INET, :IPPROTO_IP, :IP_MULTICAST_LOOP, 1)
355  * p sockopt.int => 1
356  *
357  * p Socket::Option.ipv4_multicast_loop(10)
358  * #=> #<Socket::Option: INET IP MULTICAST_LOOP 10>
359  *
360  */
361 static VALUE
363 {
364 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
365 # if defined(__NetBSD__) || defined(__OpenBSD__)
366  unsigned char i = NUM2CHR(rb_to_int(value));
367 # else
368  int i = NUM2INT(rb_to_int(value));
369 # endif
370  return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_LOOP,
371  rb_str_new((char*)&i, sizeof(i)));
372 #else
373 # error IPPROTO_IP or IP_MULTICAST_LOOP is not implemented
374 #endif
375 }
376 
377 /*
378  * call-seq:
379  * sockopt.ipv4_multicast_loop => integer
380  *
381  * Returns the ipv4_multicast_loop data in _sockopt_ as a integer.
382  *
383  * sockopt = Socket::Option.ipv4_multicast_loop(10)
384  * p sockopt.ipv4_multicast_loop => 10
385  */
386 static VALUE
388 {
389  int family = NUM2INT(sockopt_family_m(self));
390  int level = sockopt_level(self);
391  int optname = sockopt_optname(self);
392 
393 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
394  if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) {
395 # if defined(__NetBSD__) || defined(__OpenBSD__)
396  return sockopt_byte(self);
397 # else
398  return sockopt_int(self);
399 # endif
400  }
401 #endif
402  rb_raise(rb_eTypeError, "ipv4_multicast_loop socket option expected");
403  UNREACHABLE;
404 }
405 
406 #if defined(__NetBSD__) || defined(__OpenBSD__)
407 # define inspect_ipv4_multicast_loop(a,b,c,d) inspect_byte(a,b,c,d)
408 #else
409 # define inspect_ipv4_multicast_loop(a,b,c,d) inspect_int(a,b,c,d)
410 #endif
411 
412 /*
413  * call-seq:
414  * Socket::Option.ipv4_multicast_ttl(integer) => sockopt
415  *
416  * Creates a new Socket::Option object for IP_MULTICAST_TTL.
417  *
418  * The size is dependent on the platform.
419  *
420  * p Socket::Option.ipv4_multicast_ttl(10)
421  * #=> #<Socket::Option: INET IP MULTICAST_TTL 10>
422  *
423  */
424 static VALUE
426 {
427 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
428 # if defined(__NetBSD__) || defined(__OpenBSD__)
429  unsigned char i = NUM2CHR(rb_to_int(value));
430 # else
431  int i = NUM2INT(rb_to_int(value));
432 # endif
433  return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_TTL,
434  rb_str_new((char*)&i, sizeof(i)));
435 #else
436 # error IPPROTO_IP or IP_MULTICAST_TTL is not implemented
437 #endif
438 }
439 
440 /*
441  * call-seq:
442  * sockopt.ipv4_multicast_ttl => integer
443  *
444  * Returns the ipv4_multicast_ttl data in _sockopt_ as a integer.
445  *
446  * sockopt = Socket::Option.ipv4_multicast_ttl(10)
447  * p sockopt.ipv4_multicast_ttl => 10
448  */
449 static VALUE
451 {
452  int family = NUM2INT(sockopt_family_m(self));
453  int level = sockopt_level(self);
454  int optname = sockopt_optname(self);
455 
456 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
457  if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) {
458 # if defined(__NetBSD__) || defined(__OpenBSD__)
459  return sockopt_byte(self);
460 # else
461  return sockopt_int(self);
462 # endif
463  }
464 #endif
465  rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected");
466  UNREACHABLE;
467 }
468 
469 #if defined(__NetBSD__) || defined(__OpenBSD__)
470 # define inspect_ipv4_multicast_ttl(a,b,c,d) inspect_byte(a,b,c,d)
471 #else
472 # define inspect_ipv4_multicast_ttl(a,b,c,d) inspect_int(a,b,c,d)
473 #endif
474 
475 static int
476 inspect_int(int level, int optname, VALUE data, VALUE ret)
477 {
478  if (RSTRING_LEN(data) == sizeof(int)) {
479  int i;
480  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
481  rb_str_catf(ret, " %d", i);
482  return 1;
483  }
484  else {
485  return 0;
486  }
487 }
488 
489 #if defined(__NetBSD__) || defined(__OpenBSD__)
490 static int
491 inspect_byte(int level, int optname, VALUE data, VALUE ret)
492 {
493  if (RSTRING_LEN(data) == sizeof(unsigned char)) {
494  rb_str_catf(ret, " %d", (unsigned char)*RSTRING_PTR(data));
495  return 1;
496  }
497  else {
498  return 0;
499  }
500 }
501 #endif
502 
503 static int
504 inspect_errno(int level, int optname, VALUE data, VALUE ret)
505 {
506  if (RSTRING_LEN(data) == sizeof(int)) {
507  int i;
508  char *err;
509  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
510  err = strerror(i);
511  rb_str_catf(ret, " %s (%d)", err, i);
512  return 1;
513  }
514  else {
515  return 0;
516  }
517 }
518 
519 #if defined(IPV6_MULTICAST_LOOP)
520 static int
521 inspect_uint(int level, int optname, VALUE data, VALUE ret)
522 {
523  if (RSTRING_LEN(data) == sizeof(int)) {
524  unsigned int i;
525  memcpy((char*)&i, RSTRING_PTR(data), sizeof(unsigned int));
526  rb_str_catf(ret, " %u", i);
527  return 1;
528  }
529  else {
530  return 0;
531  }
532 }
533 #endif
534 
535 #if defined(SOL_SOCKET) && defined(SO_LINGER) /* POSIX */
536 static int
537 inspect_linger(int level, int optname, VALUE data, VALUE ret)
538 {
539  if (RSTRING_LEN(data) == sizeof(struct linger)) {
540  struct linger s;
541  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
542  switch (s.l_onoff) {
543  case 0: rb_str_cat2(ret, " off"); break;
544  case 1: rb_str_cat2(ret, " on"); break;
545  default: rb_str_catf(ret, " on(%d)", s.l_onoff); break;
546  }
547  rb_str_catf(ret, " %dsec", s.l_linger);
548  return 1;
549  }
550  else {
551  return 0;
552  }
553 }
554 #endif
555 
556 #if defined(SOL_SOCKET) && defined(SO_TYPE) /* POSIX */
557 static int
558 inspect_socktype(int level, int optname, VALUE data, VALUE ret)
559 {
560  if (RSTRING_LEN(data) == sizeof(int)) {
561  int i;
562  ID id;
563  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
564  id = rsock_intern_socktype(i);
565  if (id)
566  rb_str_catf(ret, " %s", rb_id2name(id));
567  else
568  rb_str_catf(ret, " %d", i);
569  return 1;
570  }
571  else {
572  return 0;
573  }
574 }
575 #endif
576 
577 static int
578 inspect_timeval_as_interval(int level, int optname, VALUE data, VALUE ret)
579 {
580  if (RSTRING_LEN(data) == sizeof(struct timeval)) {
581  struct timeval s;
582  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
583  rb_str_catf(ret, " %ld.%06ldsec", (long)s.tv_sec, (long)s.tv_usec);
584  return 1;
585  }
586  else {
587  return 0;
588  }
589 }
590 
591 /*
592  * socket option for IPv4 multicast is bit confusing.
593  *
594  * IP Multicast is implemented by Steve Deering at first:
595  * IP Multicast Extensions for 4.3BSD UNIX and related systems
596  * (MULTICAST 1.2 Release)
597  * http://www.kohala.com/start/mcast.api.txt
598  *
599  * There are 3 socket options which takes a struct.
600  *
601  * IP_MULTICAST_IF: struct in_addr
602  * IP_ADD_MEMBERSHIP: struct ip_mreq
603  * IP_DROP_MEMBERSHIP: struct ip_mreq
604  *
605  * But they uses an IP address to specify an interface.
606  * This means the API cannot specify an unnumbered interface.
607  *
608  * Linux 2.4 introduces struct ip_mreqn to fix this problem.
609  * struct ip_mreqn has imr_ifindex field to specify interface index.
610  *
611  * IP_MULTICAST_IF: struct ip_mreqn
612  * IP_ADD_MEMBERSHIP: struct ip_mreqn
613  * IP_DROP_MEMBERSHIP: struct ip_mreqn
614  *
615  * FreeBSD 7 obtained struct ip_mreqn for IP_MULTICAST_IF.
616  * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/sys/netinet/in.h.diff?r1=1.99;r2=1.100
617  *
618  * Another hackish workaround is "RFC 1724 hack".
619  * RFC 1724 section 3.3 suggests unnumbered interfaces
620  * specified by pseudo address 0.0.0.0/8.
621  * NetBSD 4 and FreeBSD 5 documented it.
622  * http://cvsweb.netbsd.org/cgi-bin/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.16&r2=1.17
623  * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.37;r2=1.38
624  * FreeBSD 7.0 removed it.
625  * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.49;r2=1.50
626  *
627  * RFC 1724 hack is not supported by Socket::Option#inspect because
628  * it is not distinguishable by the size.
629  */
630 
631 #ifndef HAVE_INET_NTOP
632 static const char *
633 inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
634 {
635 #ifdef HAVE_INET_NTOA
636  struct in_addr in;
637  memcpy(&in.s_addr, addr, sizeof(in.s_addr));
638  snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
639 #else
640  unsigned long x = ntohl(*(unsigned long*)addr);
641  snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
642  (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
643  (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
644 #endif
645  return numaddr;
646 }
647 #elif defined __MINGW64__
648 # define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l)
649 #endif
650 
651 /* Although the buffer size needed depends on the prefixes, "%u" may generate "4294967295". */
652 static int
653 rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int ifindex, char *buf, size_t len)
654 {
655 #if defined(HAVE_IF_INDEXTONAME)
656  char ifbuf[IFNAMSIZ];
657  if (if_indextoname(ifindex, ifbuf) == NULL)
658  return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
659  else
660  return snprintf(buf, len, "%s%s", succ_prefix, ifbuf);
661 #else
662 # ifndef IFNAMSIZ
663 # define IFNAMSIZ (sizeof(unsigned int)*3+1)
664 # endif
665  return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
666 #endif
667 }
668 
669 #if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQ) /* 4.4BSD, GNU/Linux */
670 static int
671 inspect_ipv4_mreq(int level, int optname, VALUE data, VALUE ret)
672 {
673  if (RSTRING_LEN(data) == sizeof(struct ip_mreq)) {
674  struct ip_mreq s;
675  char addrbuf[INET_ADDRSTRLEN];
676  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
677  if (inet_ntop(AF_INET, &s.imr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
678  rb_str_cat2(ret, " invalid-address");
679  else
680  rb_str_catf(ret, " %s", addrbuf);
681  if (inet_ntop(AF_INET, &s.imr_interface, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
682  rb_str_catf(ret, " invalid-address");
683  else
684  rb_str_catf(ret, " %s", addrbuf);
685  return 1;
686  }
687  else {
688  return 0;
689  }
690 }
691 #endif
692 
693 #if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* GNU/Linux, FreeBSD 7 */
694 static int
695 inspect_ipv4_mreqn(int level, int optname, VALUE data, VALUE ret)
696 {
697  if (RSTRING_LEN(data) == sizeof(struct ip_mreqn)) {
698  struct ip_mreqn s;
699  char addrbuf[INET_ADDRSTRLEN], ifbuf[32+IFNAMSIZ];
700  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
701  if (inet_ntop(AF_INET, &s.imr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
702  rb_str_cat2(ret, " invalid-address");
703  else
704  rb_str_catf(ret, " %s", addrbuf);
705  if (inet_ntop(AF_INET, &s.imr_address, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
706  rb_str_catf(ret, " invalid-address");
707  else
708  rb_str_catf(ret, " %s", addrbuf);
709  rb_if_indextoname(" ", " ifindex:", s.imr_ifindex, ifbuf, sizeof(ifbuf));
710  rb_str_cat2(ret, ifbuf);
711  return 1;
712  }
713  else {
714  return 0;
715  }
716 }
717 #endif
718 
719 #if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQ) /* 4.4BSD, GNU/Linux */
720 static int
721 inspect_ipv4_add_drop_membership(int level, int optname, VALUE data, VALUE ret)
722 {
723  if (RSTRING_LEN(data) == sizeof(struct ip_mreq))
724  return inspect_ipv4_mreq(level, optname, data, ret);
725 # if defined(HAVE_TYPE_STRUCT_IP_MREQN)
726  else if (RSTRING_LEN(data) == sizeof(struct ip_mreqn))
727  return inspect_ipv4_mreqn(level, optname, data, ret);
728 # endif
729  else
730  return 0;
731 }
732 #endif
733 
734 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
735 static int
736 inspect_ipv4_multicast_if(int level, int optname, VALUE data, VALUE ret)
737 {
738  if (RSTRING_LEN(data) == sizeof(struct in_addr)) {
739  struct in_addr s;
740  char addrbuf[INET_ADDRSTRLEN];
741  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
742  if (inet_ntop(AF_INET, &s, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
743  rb_str_cat2(ret, " invalid-address");
744  else
745  rb_str_catf(ret, " %s", addrbuf);
746  return 1;
747  }
748  else if (RSTRING_LEN(data) == sizeof(struct ip_mreqn)) {
749  return inspect_ipv4_mreqn(level, optname, data, ret);
750  }
751  else {
752  return 0;
753  }
754 }
755 #endif
756 
757 #if defined(IPV6_MULTICAST_IF) /* POSIX, RFC 3493 */
758 static int
759 inspect_ipv6_multicast_if(int level, int optname, VALUE data, VALUE ret)
760 {
761  if (RSTRING_LEN(data) == sizeof(int)) {
762  char ifbuf[32+IFNAMSIZ];
763  unsigned int ifindex;
764  memcpy((char*)&ifindex, RSTRING_PTR(data), sizeof(unsigned int));
765  rb_if_indextoname(" ", " ", ifindex, ifbuf, sizeof(ifbuf));
766  rb_str_cat2(ret, ifbuf);
767  return 1;
768  }
769  else {
770  return 0;
771  }
772 }
773 #endif
774 
775 #if defined(IPPROTO_IPV6) && defined(HAVE_TYPE_STRUCT_IPV6_MREQ) /* POSIX, RFC 3493 */
776 static int
777 inspect_ipv6_mreq(int level, int optname, VALUE data, VALUE ret)
778 {
779  if (RSTRING_LEN(data) == sizeof(struct ipv6_mreq)) {
780  struct ipv6_mreq s;
781  char addrbuf[INET6_ADDRSTRLEN], ifbuf[32+IFNAMSIZ];
782  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
783  if (inet_ntop(AF_INET6, &s.ipv6mr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
784  rb_str_cat2(ret, " invalid-address");
785  else
786  rb_str_catf(ret, " %s", addrbuf);
787  rb_if_indextoname(" ", " interface:", s.ipv6mr_interface, ifbuf, sizeof(ifbuf));
788  rb_str_cat2(ret, ifbuf);
789  return 1;
790  }
791  else {
792  return 0;
793  }
794 }
795 #endif
796 
797 #if defined(SOL_SOCKET) && defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
798 #if defined(__OpenBSD__)
799 #define RUBY_SOCK_PEERCRED struct sockpeercred
800 #else
801 #define RUBY_SOCK_PEERCRED struct ucred
802 #endif
803 static int
804 inspect_peercred(int level, int optname, VALUE data, VALUE ret)
805 {
806  if (RSTRING_LEN(data) == sizeof(RUBY_SOCK_PEERCRED)) {
807  RUBY_SOCK_PEERCRED cred;
808  memcpy(&cred, RSTRING_PTR(data), sizeof(RUBY_SOCK_PEERCRED));
809  rb_str_catf(ret, " pid=%u euid=%u egid=%u",
810  (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid);
811  rb_str_cat2(ret, " (ucred)");
812  return 1;
813  }
814  else {
815  return 0;
816  }
817 }
818 #endif
819 
820 #if defined(LOCAL_PEERCRED) /* FreeBSD, MacOS X */
821 static int
822 inspect_local_peercred(int level, int optname, VALUE data, VALUE ret)
823 {
824  if (RSTRING_LEN(data) == sizeof(struct xucred)) {
825  struct xucred cred;
826  memcpy(&cred, RSTRING_PTR(data), sizeof(struct xucred));
827  if (cred.cr_version != XUCRED_VERSION)
828  return 0;
829  rb_str_catf(ret, " version=%u", cred.cr_version);
830  rb_str_catf(ret, " euid=%u", cred.cr_uid);
831  if (cred.cr_ngroups) {
832  int i;
833  const char *sep = " groups=";
834  for (i = 0; i < cred.cr_ngroups; i++) {
835  rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]);
836  sep = ",";
837  }
838  }
839  rb_str_cat2(ret, " (xucred)");
840  return 1;
841  }
842  else {
843  return 0;
844  }
845 }
846 #endif
847 
848 
849 /*
850  * call-seq:
851  * sockopt.inspect => string
852  *
853  * Returns a string which shows sockopt in human-readable form.
854  *
855  * p Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i")).inspect
856  * #=> "#<Socket::Option: INET SOCKET KEEPALIVE 1>"
857  *
858  */
859 static VALUE
861 {
862  int family = NUM2INT(sockopt_family_m(self));
863  int level = NUM2INT(sockopt_level_m(self));
864  int optname = NUM2INT(sockopt_optname_m(self));
865  VALUE data = sockopt_data(self);
866  VALUE v, ret;
867  ID family_id, level_id, optname_id;
868  int inspected;
869 
870  StringValue(data);
871 
872  ret = rb_sprintf("#<%s:", rb_obj_classname(self));
873 
874  family_id = rsock_intern_family_noprefix(family);
875  if (family_id)
876  rb_str_catf(ret, " %s", rb_id2name(family_id));
877  else
878  rb_str_catf(ret, " family:%d", family);
879 
880  if (level == SOL_SOCKET) {
881  rb_str_cat2(ret, " SOCKET");
882 
883  optname_id = rsock_intern_so_optname(optname);
884  if (optname_id)
885  rb_str_catf(ret, " %s", rb_id2name(optname_id));
886  else
887  rb_str_catf(ret, " optname:%d", optname);
888  }
889 #ifdef HAVE_SYS_UN_H
890  else if (family == AF_UNIX) {
891  rb_str_catf(ret, " level:%d", level);
892 
893  optname_id = rsock_intern_local_optname(optname);
894  if (optname_id)
895  rb_str_catf(ret, " %s", rb_id2name(optname_id));
896  else
897  rb_str_catf(ret, " optname:%d", optname);
898  }
899 #endif
900  else if (IS_IP_FAMILY(family)) {
901  level_id = rsock_intern_iplevel(level);
902  if (level_id)
903  rb_str_catf(ret, " %s", rb_id2name(level_id));
904  else
905  rb_str_catf(ret, " level:%d", level);
906 
907  v = optname_to_sym(level, optname);
908  if (SYMBOL_P(v))
909  rb_str_catf(ret, " %s", rb_id2name(SYM2ID(v)));
910  else
911  rb_str_catf(ret, " optname:%d", optname);
912  }
913  else {
914  rb_str_catf(ret, " level:%d", level);
915  rb_str_catf(ret, " optname:%d", optname);
916  }
917 
918  inspected = 0;
919 
920  if (level == SOL_SOCKET)
921  family = AF_UNSPEC;
922  switch (family) {
923  case AF_UNSPEC:
924  switch (level) {
925  case SOL_SOCKET:
926  switch (optname) {
927 # if defined(SO_DEBUG) /* POSIX */
928  case SO_DEBUG: inspected = inspect_int(level, optname, data, ret); break;
929 # endif
930 # if defined(SO_ERROR) /* POSIX */
931  case SO_ERROR: inspected = inspect_errno(level, optname, data, ret); break;
932 # endif
933 # if defined(SO_TYPE) /* POSIX */
934  case SO_TYPE: inspected = inspect_socktype(level, optname, data, ret); break;
935 # endif
936 # if defined(SO_ACCEPTCONN) /* POSIX */
937  case SO_ACCEPTCONN: inspected = inspect_int(level, optname, data, ret); break;
938 # endif
939 # if defined(SO_BROADCAST) /* POSIX */
940  case SO_BROADCAST: inspected = inspect_int(level, optname, data, ret); break;
941 # endif
942 # if defined(SO_REUSEADDR) /* POSIX */
943  case SO_REUSEADDR: inspected = inspect_int(level, optname, data, ret); break;
944 # endif
945 # if defined(SO_KEEPALIVE) /* POSIX */
946  case SO_KEEPALIVE: inspected = inspect_int(level, optname, data, ret); break;
947 # endif
948 # if defined(SO_OOBINLINE) /* POSIX */
949  case SO_OOBINLINE: inspected = inspect_int(level, optname, data, ret); break;
950 # endif
951 # if defined(SO_SNDBUF) /* POSIX */
952  case SO_SNDBUF: inspected = inspect_int(level, optname, data, ret); break;
953 # endif
954 # if defined(SO_RCVBUF) /* POSIX */
955  case SO_RCVBUF: inspected = inspect_int(level, optname, data, ret); break;
956 # endif
957 # if defined(SO_DONTROUTE) /* POSIX */
958  case SO_DONTROUTE: inspected = inspect_int(level, optname, data, ret); break;
959 # endif
960 # if defined(SO_RCVLOWAT) /* POSIX */
961  case SO_RCVLOWAT: inspected = inspect_int(level, optname, data, ret); break;
962 # endif
963 # if defined(SO_SNDLOWAT) /* POSIX */
964  case SO_SNDLOWAT: inspected = inspect_int(level, optname, data, ret); break;
965 # endif
966 # if defined(SO_LINGER) /* POSIX */
967  case SO_LINGER: inspected = inspect_linger(level, optname, data, ret); break;
968 # endif
969 # if defined(SO_RCVTIMEO) /* POSIX */
970  case SO_RCVTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
971 # endif
972 # if defined(SO_SNDTIMEO) /* POSIX */
973  case SO_SNDTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
974 # endif
975 # if defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
976  case SO_PEERCRED: inspected = inspect_peercred(level, optname, data, ret); break;
977 # endif
978  }
979  break;
980  }
981  break;
982 
983  case AF_INET:
984 #ifdef INET6
985  case AF_INET6:
986 #endif
987  switch (level) {
988 # if defined(IPPROTO_IP)
989  case IPPROTO_IP:
990  switch (optname) {
991 # if defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
992  case IP_MULTICAST_IF: inspected = inspect_ipv4_multicast_if(level, optname, data, ret); break;
993 # endif
994 # if defined(IP_ADD_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
995  case IP_ADD_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
996 # endif
997 # if defined(IP_DROP_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
998  case IP_DROP_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
999 # endif
1000 # if defined(IP_MULTICAST_LOOP) /* 4.4BSD, GNU/Linux */
1001  case IP_MULTICAST_LOOP: inspected = inspect_ipv4_multicast_loop(level, optname, data, ret); break;
1002 # endif
1003 # if defined(IP_MULTICAST_TTL) /* 4.4BSD, GNU/Linux */
1004  case IP_MULTICAST_TTL: inspected = inspect_ipv4_multicast_ttl(level, optname, data, ret); break;
1005 # endif
1006  }
1007  break;
1008 # endif
1009 
1010 # if defined(IPPROTO_IPV6)
1011  case IPPROTO_IPV6:
1012  switch (optname) {
1013 # if defined(IPV6_MULTICAST_HOPS) /* POSIX */
1014  case IPV6_MULTICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
1015 # endif
1016 # if defined(IPV6_MULTICAST_IF) /* POSIX */
1017  case IPV6_MULTICAST_IF: inspected = inspect_ipv6_multicast_if(level, optname, data, ret); break;
1018 # endif
1019 # if defined(IPV6_MULTICAST_LOOP) /* POSIX */
1020  case IPV6_MULTICAST_LOOP: inspected = inspect_uint(level, optname, data, ret); break;
1021 # endif
1022 # if defined(IPV6_JOIN_GROUP) /* POSIX */
1023  case IPV6_JOIN_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
1024 # endif
1025 # if defined(IPV6_LEAVE_GROUP) /* POSIX */
1026  case IPV6_LEAVE_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
1027 # endif
1028 # if defined(IPV6_UNICAST_HOPS) /* POSIX */
1029  case IPV6_UNICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
1030 # endif
1031 # if defined(IPV6_V6ONLY) /* POSIX */
1032  case IPV6_V6ONLY: inspected = inspect_int(level, optname, data, ret); break;
1033 # endif
1034  }
1035  break;
1036 # endif
1037 
1038 # if defined(IPPROTO_TCP)
1039  case IPPROTO_TCP:
1040  switch (optname) {
1041 # if defined(TCP_NODELAY) /* POSIX */
1042  case TCP_NODELAY: inspected = inspect_int(level, optname, data, ret); break;
1043 # endif
1044  }
1045  break;
1046 # endif
1047  }
1048  break;
1049 
1050 #ifdef HAVE_SYS_UN_H
1051  case AF_UNIX:
1052  switch (level) {
1053  case 0:
1054  switch (optname) {
1055 # if defined(LOCAL_PEERCRED)
1056  case LOCAL_PEERCRED: inspected = inspect_local_peercred(level, optname, data, ret); break;
1057 # endif
1058  }
1059  break;
1060  }
1061  break;
1062 #endif
1063  }
1064 
1065  if (!inspected) {
1066  rb_str_cat2(ret, " ");
1067  rb_str_append(ret, rb_str_dump(data));
1068  }
1069 
1070  rb_str_cat2(ret, ">");
1071 
1072  return ret;
1073 }
1074 
1075 /*
1076  * call-seq:
1077  * sockopt.unpack(template) => array
1078  *
1079  * Calls String#unpack on sockopt.data.
1080  *
1081  * sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
1082  * p sockopt.unpack("i") #=> [1]
1083  * p sockopt.data.unpack("i") #=> [1]
1084  */
1085 static VALUE
1086 sockopt_unpack(VALUE self, VALUE template)
1087 {
1088  return rb_funcall(sockopt_data(self), rb_intern("unpack"), 1, template);
1089 }
1090 
1091 void
1093 {
1094  /*
1095  * Document-class: Socket::Option
1096  *
1097  * Socket::Option represents a socket option used by
1098  * BasicSocket#getsockopt and BasicSocket#setsockopt. A socket option
1099  * contains the socket #family, protocol #level, option name #optname and
1100  * option value #data.
1101  */
1103  rb_define_method(rb_cSockOpt, "initialize", sockopt_initialize, 4);
1109 
1112 
1115 
1118 
1121 
1123  rb_define_method(rb_cSockOpt, "ipv4_multicast_ttl", sockopt_ipv4_multicast_ttl, 0);
1124 
1126  rb_define_method(rb_cSockOpt, "ipv4_multicast_loop", sockopt_ipv4_multicast_loop, 0);
1127 
1129 
1130  rb_define_method(rb_cSockOpt, "to_s", sockopt_data, 0); /* compatibility for ruby before 1.9.2 */
1131 }
1132 
VALUE data
Definition: tcltklib.c:3360
VALUE rb_to_int(VALUE)
Definition: object.c:2700
static VALUE sockopt_unpack(VALUE self, VALUE template)
Definition: option.c:1086
memo u1 value
Definition: enum.c:587
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
static VALUE sockopt_family_m(VALUE self)
Definition: option.c:80
static VALUE sockopt_bool(VALUE self)
Definition: option.c:268
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1646
rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts))
static int rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int ifindex, char *buf, size_t len)
Definition: option.c:653
static VALUE sockopt_inspect(VALUE self)
Definition: option.c:860
int ret
Definition: tcltklib.c:285
long tv_sec
Definition: ossl_asn1.c:17
VALUE rb_eTypeError
Definition: error.c:548
static VALUE optname_to_sym(int level, int optname)
Definition: option.c:17
#define UNREACHABLE
Definition: ruby.h:42
static int inspect_timeval_as_interval(int level, int optname, VALUE data, VALUE ret)
Definition: option.c:578
rb_str_append(str, i)
#define RSTRING_PTR(str)
static VALUE sockopt_linger(VALUE self)
Definition: option.c:323
NIL_P(eventloop_thread)
Definition: tcltklib.c:4056
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:657
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
return Qtrue
Definition: tcltklib.c:9618
tmp
Definition: enum.c:447
#define ID2SYM(x)
#define T_OBJECT
i
Definition: enum.c:446
static VALUE sockopt_level_m(VALUE self)
Definition: option.c:101
VALUE rb_str_dump(VALUE)
Definition: string.c:4902
memset(y->frac+ix+1, 0,(y->Prec-(ix+1))*sizeof(BDIGIT))
static VALUE sockopt_ipv4_multicast_ttl(VALUE self)
Definition: option.c:450
static VALUE sockopt_data(VALUE self)
Definition: option.c:138
return Qfalse
Definition: tcltklib.c:6790
int rsock_family_arg(VALUE domain)
Definition: constants.c:43
VALUE rsock_sockopt_new(int family, int level, int optname, VALUE data)
Definition: option.c:62
long tv_usec
Definition: ossl_asn1.c:18
static VALUE sockopt_initialize(VALUE self, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE data)
Definition: option.c:48
static int inspect_errno(int level, int optname, VALUE data, VALUE ret)
Definition: option.c:504
static VALUE sockopt_s_bool(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vbool)
Definition: option.c:249
unsigned long ID
Definition: ripper.y:89
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2158
static VALUE VALUE obj
Definition: tcltklib.c:3150
#define RSTRING_LEN(str)
int rsock_level_arg(int family, VALUE level)
Definition: constants.c:57
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2686
#define inspect_ipv4_multicast_loop(a, b, c, d)
Definition: option.c:409
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
int err
Definition: win32.c:114
int len
Definition: enumerator.c:1332
VALUE rb_cSocket
Definition: init.c:22
#define CHR2FIX(x)
gz level
Definition: zlib.c:2264
static VALUE constant_to_sym(int constant, ID(*intern_const)(int))
Definition: option.c:6
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:154
memcpy(buf+1, str, len)
#define RTEST(v)
const int id
Definition: nkf.c:209
static int sockopt_optname(VALUE self)
Definition: option.c:107
int socklen_t
Definition: getaddrinfo.c:84
static VALUE sockopt_s_byte(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
Definition: option.c:157
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1250
#define StringValue(v)
VALUE v
Definition: enum.c:845
register char * s
Definition: os2.c:56
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:620
static const char * inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
Definition: option.c:633
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1127
static VALUE sockopt_ipv4_multicast_loop(VALUE self)
Definition: option.c:387
static VALUE sockopt_optname_m(VALUE self)
Definition: option.c:122
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
#define NEWOBJ_OF(obj, type, klass, flags)
#define SYMBOL_P(x)
static int inspect_int(int level, int optname, VALUE data, VALUE ret)
Definition: option.c:476
static VALUE sockopt_int(VALUE self)
Definition: option.c:222
VALUE name
Definition: enum.c:572
static VALUE sockopt_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
Definition: option.c:201
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1290
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1561
static VALUE sockopt_s_ipv4_multicast_loop(VALUE klass, VALUE value)
Definition: option.c:362
#define AF_UNSPEC
Definition: sockport.h:101
klass
Definition: tcltklib.c:3496
#define INT2NUM(x)
static VALUE sockopt_s_linger(VALUE klass, VALUE vonoff, VALUE vsecs)
Definition: option.c:300
int rsock_optname_arg(int family, int level, VALUE optname)
Definition: constants.c:69
rb_ivar_set(yielder, id_memo, LONG2NUM(++count))
VALUE rb_cSockOpt
Definition: option.c:3
VALUE rb_str_new(const char *, long)
Definition: string.c:534
#define NUM2INT(x)
const char * rb_id2name(ID id)
Definition: ripper.c:17271
static int sockopt_level(VALUE self)
Definition: option.c:86
#define IFNAMSIZ
#define NUM2CHR(x)
unsigned long VALUE
Definition: ripper.y:88
void rsock_init_sockopt(void)
Definition: option.c:1092
#define inspect_ipv4_multicast_ttl(a, b, c, d)
Definition: option.c:472
static VALUE sockopt_byte(VALUE self)
Definition: option.c:178
#define snprintf
static VALUE sockopt_s_ipv4_multicast_ttl(VALUE klass, VALUE value)
Definition: option.c:425
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1479
#define SYM2ID(x)