Ruby  2.1.4p265(2014-10-27revision48166)
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:
22  case IPPROTO_IP:
24 #ifdef IPPROTO_IPV6
25  case IPPROTO_IPV6:
27 #endif
28  case IPPROTO_TCP:
30  case IPPROTO_UDP:
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 {
64  NEWOBJ_OF(obj, struct RObject, rb_cSockOpt, T_OBJECT);
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  VALUE data = sockopt_data(self);
272  StringValue(data);
273  if (RSTRING_LEN(data) != sizeof(int))
274  rb_raise(rb_eTypeError, "size differ. expected as sizeof(int)=%d but %ld",
275  (int)sizeof(int), (long)RSTRING_LEN(data));
276  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
277  return i == 0 ? Qfalse : Qtrue;
278 }
279 
280 /*
281  * call-seq:
282  * Socket::Option.linger(onoff, secs) => sockopt
283  *
284  * Creates a new Socket::Option object for SOL_SOCKET/SO_LINGER.
285  *
286  * _onoff_ should be an integer or a boolean.
287  *
288  * _secs_ should be the number of seconds.
289  *
290  * p Socket::Option.linger(true, 10)
291  * #=> #<Socket::Option: UNSPEC SOCKET LINGER on 10sec>
292  *
293  */
294 static VALUE
295 sockopt_s_linger(VALUE klass, VALUE vonoff, VALUE vsecs)
296 {
297  VALUE tmp;
298  struct linger l;
299  memset(&l, 0, sizeof(l));
300  if (!NIL_P(tmp = rb_check_to_integer(vonoff, "to_int")))
301  l.l_onoff = NUM2INT(tmp);
302  else
303  l.l_onoff = RTEST(vonoff) ? 1 : 0;
304  l.l_linger = NUM2INT(vsecs);
305  return rsock_sockopt_new(AF_UNSPEC, SOL_SOCKET, SO_LINGER, rb_str_new((char*)&l, sizeof(l)));
306 }
307 
308 /*
309  * call-seq:
310  * sockopt.linger => [bool, seconds]
311  *
312  * Returns the linger data in _sockopt_ as a pair of boolean and integer.
313  *
314  * sockopt = Socket::Option.linger(true, 10)
315  * p sockopt.linger => [true, 10]
316  */
317 static VALUE
319 {
320  int level = sockopt_level(self);
321  int optname = sockopt_optname(self);
322  VALUE data = sockopt_data(self);
323  struct linger l;
324  VALUE vonoff, vsecs;
325 
326  if (level != SOL_SOCKET || optname != SO_LINGER)
327  rb_raise(rb_eTypeError, "linger socket option expected");
328  if (RSTRING_LEN(data) != sizeof(l))
329  rb_raise(rb_eTypeError, "size differ. expected as sizeof(struct linger)=%d but %ld",
330  (int)sizeof(struct linger), (long)RSTRING_LEN(data));
331  memcpy((char*)&l, RSTRING_PTR(data), sizeof(struct linger));
332  switch (l.l_onoff) {
333  case 0: vonoff = Qfalse; break;
334  case 1: vonoff = Qtrue; break;
335  default: vonoff = INT2NUM(l.l_onoff); break;
336  }
337  vsecs = INT2NUM(l.l_linger);
338  return rb_assoc_new(vonoff, vsecs);
339 }
340 
341 /*
342  * call-seq:
343  * Socket::Option.ipv4_multicast_loop(integer) => sockopt
344  *
345  * Creates a new Socket::Option object for IP_MULTICAST_LOOP.
346  *
347  * The size is dependent on the platform.
348  *
349  * sockopt = Socket::Option.int(:INET, :IPPROTO_IP, :IP_MULTICAST_LOOP, 1)
350  * p sockopt.int => 1
351  *
352  * p Socket::Option.ipv4_multicast_loop(10)
353  * #=> #<Socket::Option: INET IP MULTICAST_LOOP 10>
354  *
355  */
356 static VALUE
358 {
359 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
360 # if defined(__NetBSD__) || defined(__OpenBSD__)
361  unsigned char i = NUM2CHR(rb_to_int(value));
362 # else
363  int i = NUM2INT(rb_to_int(value));
364 # endif
365  return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_LOOP,
366  rb_str_new((char*)&i, sizeof(i)));
367 #else
368 # error IPPROTO_IP or IP_MULTICAST_LOOP is not implemented
369 #endif
370 }
371 
372 /*
373  * call-seq:
374  * sockopt.ipv4_multicast_loop => integer
375  *
376  * Returns the ipv4_multicast_loop data in _sockopt_ as a integer.
377  *
378  * sockopt = Socket::Option.ipv4_multicast_loop(10)
379  * p sockopt.ipv4_multicast_loop => 10
380  */
381 static VALUE
383 {
384  int family = NUM2INT(sockopt_family_m(self));
385  int level = sockopt_level(self);
386  int optname = sockopt_optname(self);
387 
388 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_LOOP)
389  if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_LOOP) {
390 # if defined(__NetBSD__) || defined(__OpenBSD__)
391  return sockopt_byte(self);
392 # else
393  return sockopt_int(self);
394 # endif
395  }
396 #endif
397  rb_raise(rb_eTypeError, "ipv4_multicast_loop socket option expected");
398  UNREACHABLE;
399 }
400 
401 #if defined(__NetBSD__) || defined(__OpenBSD__)
402 # define inspect_ipv4_multicast_loop(a,b,c,d) inspect_byte(a,b,c,d)
403 #else
404 # define inspect_ipv4_multicast_loop(a,b,c,d) inspect_int(a,b,c,d)
405 #endif
406 
407 /*
408  * call-seq:
409  * Socket::Option.ipv4_multicast_ttl(integer) => sockopt
410  *
411  * Creates a new Socket::Option object for IP_MULTICAST_TTL.
412  *
413  * The size is dependent on the platform.
414  *
415  * p Socket::Option.ipv4_multicast_ttl(10)
416  * #=> #<Socket::Option: INET IP MULTICAST_TTL 10>
417  *
418  */
419 static VALUE
421 {
422 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
423 # if defined(__NetBSD__) || defined(__OpenBSD__)
424  unsigned char i = NUM2CHR(rb_to_int(value));
425 # else
426  int i = NUM2INT(rb_to_int(value));
427 # endif
428  return rsock_sockopt_new(AF_INET, IPPROTO_IP, IP_MULTICAST_TTL,
429  rb_str_new((char*)&i, sizeof(i)));
430 #else
431 # error IPPROTO_IP or IP_MULTICAST_TTL is not implemented
432 #endif
433 }
434 
435 /*
436  * call-seq:
437  * sockopt.ipv4_multicast_ttl => integer
438  *
439  * Returns the ipv4_multicast_ttl data in _sockopt_ as a integer.
440  *
441  * sockopt = Socket::Option.ipv4_multicast_ttl(10)
442  * p sockopt.ipv4_multicast_ttl => 10
443  */
444 static VALUE
446 {
447  int family = NUM2INT(sockopt_family_m(self));
448  int level = sockopt_level(self);
449  int optname = sockopt_optname(self);
450 
451 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_TTL)
452  if (family == AF_INET && level == IPPROTO_IP && optname == IP_MULTICAST_TTL) {
453 # if defined(__NetBSD__) || defined(__OpenBSD__)
454  return sockopt_byte(self);
455 # else
456  return sockopt_int(self);
457 # endif
458  }
459 #endif
460  rb_raise(rb_eTypeError, "ipv4_multicast_ttl socket option expected");
461  UNREACHABLE;
462 }
463 
464 #if defined(__NetBSD__) || defined(__OpenBSD__)
465 # define inspect_ipv4_multicast_ttl(a,b,c,d) inspect_byte(a,b,c,d)
466 #else
467 # define inspect_ipv4_multicast_ttl(a,b,c,d) inspect_int(a,b,c,d)
468 #endif
469 
470 static int
471 inspect_int(int level, int optname, VALUE data, VALUE ret)
472 {
473  if (RSTRING_LEN(data) == sizeof(int)) {
474  int i;
475  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
476  rb_str_catf(ret, " %d", i);
477  return 1;
478  }
479  else {
480  return 0;
481  }
482 }
483 
484 #if defined(__NetBSD__) || defined(__OpenBSD__)
485 static int
486 inspect_byte(int level, int optname, VALUE data, VALUE ret)
487 {
488  if (RSTRING_LEN(data) == sizeof(unsigned char)) {
489  rb_str_catf(ret, " %d", (unsigned char)*RSTRING_PTR(data));
490  return 1;
491  }
492  else {
493  return 0;
494  }
495 }
496 #endif
497 
498 static int
499 inspect_errno(int level, int optname, VALUE data, VALUE ret)
500 {
501  if (RSTRING_LEN(data) == sizeof(int)) {
502  int i;
503  char *err;
504  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
505  err = strerror(i);
506  rb_str_catf(ret, " %s (%d)", err, i);
507  return 1;
508  }
509  else {
510  return 0;
511  }
512 }
513 
514 #if defined(IPV6_MULTICAST_LOOP)
515 static int
516 inspect_uint(int level, int optname, VALUE data, VALUE ret)
517 {
518  if (RSTRING_LEN(data) == sizeof(int)) {
519  unsigned int i;
520  memcpy((char*)&i, RSTRING_PTR(data), sizeof(unsigned int));
521  rb_str_catf(ret, " %u", i);
522  return 1;
523  }
524  else {
525  return 0;
526  }
527 }
528 #endif
529 
530 #if defined(SOL_SOCKET) && defined(SO_LINGER) /* POSIX */
531 static int
532 inspect_linger(int level, int optname, VALUE data, VALUE ret)
533 {
534  if (RSTRING_LEN(data) == sizeof(struct linger)) {
535  struct linger s;
536  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
537  switch (s.l_onoff) {
538  case 0: rb_str_cat2(ret, " off"); break;
539  case 1: rb_str_cat2(ret, " on"); break;
540  default: rb_str_catf(ret, " on(%d)", s.l_onoff); break;
541  }
542  rb_str_catf(ret, " %dsec", s.l_linger);
543  return 1;
544  }
545  else {
546  return 0;
547  }
548 }
549 #endif
550 
551 #if defined(SOL_SOCKET) && defined(SO_TYPE) /* POSIX */
552 static int
553 inspect_socktype(int level, int optname, VALUE data, VALUE ret)
554 {
555  if (RSTRING_LEN(data) == sizeof(int)) {
556  int i;
557  ID id;
558  memcpy((char*)&i, RSTRING_PTR(data), sizeof(int));
559  id = rsock_intern_socktype(i);
560  if (id)
561  rb_str_catf(ret, " %s", rb_id2name(id));
562  else
563  rb_str_catf(ret, " %d", i);
564  return 1;
565  }
566  else {
567  return 0;
568  }
569 }
570 #endif
571 
572 static int
573 inspect_timeval_as_interval(int level, int optname, VALUE data, VALUE ret)
574 {
575  if (RSTRING_LEN(data) == sizeof(struct timeval)) {
576  struct timeval s;
577  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
578  rb_str_catf(ret, " %ld.%06ldsec", (long)s.tv_sec, (long)s.tv_usec);
579  return 1;
580  }
581  else {
582  return 0;
583  }
584 }
585 
586 /*
587  * socket option for IPv4 multicast is bit confusing.
588  *
589  * IP Multicast is implemented by Steve Deering at first:
590  * IP Multicast Extensions for 4.3BSD UNIX and related systems
591  * (MULTICAST 1.2 Release)
592  * http://www.kohala.com/start/mcast.api.txt
593  *
594  * There are 3 socket options which takes a struct.
595  *
596  * IP_MULTICAST_IF: struct in_addr
597  * IP_ADD_MEMBERSHIP: struct ip_mreq
598  * IP_DROP_MEMBERSHIP: struct ip_mreq
599  *
600  * But they uses an IP address to specify an interface.
601  * This means the API cannot specify an unnumbered interface.
602  *
603  * Linux 2.4 introduces struct ip_mreqn to fix this problem.
604  * struct ip_mreqn has imr_ifindex field to specify interface index.
605  *
606  * IP_MULTICAST_IF: struct ip_mreqn
607  * IP_ADD_MEMBERSHIP: struct ip_mreqn
608  * IP_DROP_MEMBERSHIP: struct ip_mreqn
609  *
610  * FreeBSD 7 obtained struct ip_mreqn for IP_MULTICAST_IF.
611  * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/sys/netinet/in.h.diff?r1=1.99;r2=1.100
612  *
613  * Another hackish workaround is "RFC 1724 hack".
614  * RFC 1724 section 3.3 suggests unnumbered interfaces
615  * specified by pseudo address 0.0.0.0/8.
616  * NetBSD 4 and FreeBSD 5 documented it.
617  * http://cvsweb.netbsd.org/cgi-bin/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.16&r2=1.17
618  * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.37;r2=1.38
619  * FreeBSD 7.0 removed it.
620  * http://www.FreeBSD.org/cgi/cvsweb.cgi/src/share/man/man4/ip.4.diff?r1=1.49;r2=1.50
621  *
622  * RFC 1724 hack is not supported by Socket::Option#inspect because
623  * it is not distinguishable by the size.
624  */
625 
626 #ifndef HAVE_INET_NTOP
627 static const char *
628 inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
629 {
630 #ifdef HAVE_INET_NTOA
631  struct in_addr in;
632  memcpy(&in.s_addr, addr, sizeof(in.s_addr));
633  snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
634 #else
635  unsigned long x = ntohl(*(unsigned long*)addr);
636  snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
637  (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
638  (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
639 #endif
640  return numaddr;
641 }
642 #elif defined __MINGW64__
643 # define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l)
644 #endif
645 
646 /* Although the buffer size needed depends on the prefixes, "%u" may generate "4294967295". */
647 static int
648 rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int ifindex, char *buf, size_t len)
649 {
650 #if defined(HAVE_IF_INDEXTONAME)
651  char ifbuf[IFNAMSIZ];
652  if (if_indextoname(ifindex, ifbuf) == NULL)
653  return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
654  else
655  return snprintf(buf, len, "%s%s", succ_prefix, ifbuf);
656 #else
657 # ifndef IFNAMSIZ
658 # define IFNAMSIZ (sizeof(unsigned int)*3+1)
659 # endif
660  return snprintf(buf, len, "%s%u", fail_prefix, ifindex);
661 #endif
662 }
663 
664 #if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQ) /* 4.4BSD, GNU/Linux */
665 static int
666 inspect_ipv4_mreq(int level, int optname, VALUE data, VALUE ret)
667 {
668  if (RSTRING_LEN(data) == sizeof(struct ip_mreq)) {
669  struct ip_mreq s;
670  char addrbuf[INET_ADDRSTRLEN];
671  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
672  if (inet_ntop(AF_INET, &s.imr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
673  rb_str_cat2(ret, " invalid-address");
674  else
675  rb_str_catf(ret, " %s", addrbuf);
676  if (inet_ntop(AF_INET, &s.imr_interface, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
677  rb_str_catf(ret, " invalid-address");
678  else
679  rb_str_catf(ret, " %s", addrbuf);
680  return 1;
681  }
682  else {
683  return 0;
684  }
685 }
686 #endif
687 
688 #if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* GNU/Linux, FreeBSD 7 */
689 static int
690 inspect_ipv4_mreqn(int level, int optname, VALUE data, VALUE ret)
691 {
692  if (RSTRING_LEN(data) == sizeof(struct ip_mreqn)) {
693  struct ip_mreqn s;
694  char addrbuf[INET_ADDRSTRLEN], ifbuf[32+IFNAMSIZ];
695  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
696  if (inet_ntop(AF_INET, &s.imr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
697  rb_str_cat2(ret, " invalid-address");
698  else
699  rb_str_catf(ret, " %s", addrbuf);
700  if (inet_ntop(AF_INET, &s.imr_address, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
701  rb_str_catf(ret, " invalid-address");
702  else
703  rb_str_catf(ret, " %s", addrbuf);
704  rb_if_indextoname(" ", " ifindex:", s.imr_ifindex, ifbuf, sizeof(ifbuf));
705  rb_str_cat2(ret, ifbuf);
706  return 1;
707  }
708  else {
709  return 0;
710  }
711 }
712 #endif
713 
714 #if defined(IPPROTO_IP) && defined(HAVE_TYPE_STRUCT_IP_MREQ) /* 4.4BSD, GNU/Linux */
715 static int
716 inspect_ipv4_add_drop_membership(int level, int optname, VALUE data, VALUE ret)
717 {
718  if (RSTRING_LEN(data) == sizeof(struct ip_mreq))
719  return inspect_ipv4_mreq(level, optname, data, ret);
720 # if defined(HAVE_TYPE_STRUCT_IP_MREQN)
721  else if (RSTRING_LEN(data) == sizeof(struct ip_mreqn))
722  return inspect_ipv4_mreqn(level, optname, data, ret);
723 # endif
724  else
725  return 0;
726 }
727 #endif
728 
729 #if defined(IPPROTO_IP) && defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
730 static int
731 inspect_ipv4_multicast_if(int level, int optname, VALUE data, VALUE ret)
732 {
733  if (RSTRING_LEN(data) == sizeof(struct in_addr)) {
734  struct in_addr s;
735  char addrbuf[INET_ADDRSTRLEN];
736  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
737  if (inet_ntop(AF_INET, &s, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
738  rb_str_cat2(ret, " invalid-address");
739  else
740  rb_str_catf(ret, " %s", addrbuf);
741  return 1;
742  }
743  else if (RSTRING_LEN(data) == sizeof(struct ip_mreqn)) {
744  return inspect_ipv4_mreqn(level, optname, data, ret);
745  }
746  else {
747  return 0;
748  }
749 }
750 #endif
751 
752 #if defined(IPV6_MULTICAST_IF) /* POSIX, RFC 3493 */
753 static int
754 inspect_ipv6_multicast_if(int level, int optname, VALUE data, VALUE ret)
755 {
756  if (RSTRING_LEN(data) == sizeof(int)) {
757  char ifbuf[32+IFNAMSIZ];
758  unsigned int ifindex;
759  memcpy((char*)&ifindex, RSTRING_PTR(data), sizeof(unsigned int));
760  rb_if_indextoname(" ", " ", ifindex, ifbuf, sizeof(ifbuf));
761  rb_str_cat2(ret, ifbuf);
762  return 1;
763  }
764  else {
765  return 0;
766  }
767 }
768 #endif
769 
770 #if defined(IPPROTO_IPV6) && defined(HAVE_TYPE_STRUCT_IPV6_MREQ) /* POSIX, RFC 3493 */
771 static int
772 inspect_ipv6_mreq(int level, int optname, VALUE data, VALUE ret)
773 {
774  if (RSTRING_LEN(data) == sizeof(struct ipv6_mreq)) {
775  struct ipv6_mreq s;
776  char addrbuf[INET6_ADDRSTRLEN], ifbuf[32+IFNAMSIZ];
777  memcpy((char*)&s, RSTRING_PTR(data), sizeof(s));
778  if (inet_ntop(AF_INET6, &s.ipv6mr_multiaddr, addrbuf, (socklen_t)sizeof(addrbuf)) == NULL)
779  rb_str_cat2(ret, " invalid-address");
780  else
781  rb_str_catf(ret, " %s", addrbuf);
782  rb_if_indextoname(" ", " interface:", s.ipv6mr_interface, ifbuf, sizeof(ifbuf));
783  rb_str_cat2(ret, ifbuf);
784  return 1;
785  }
786  else {
787  return 0;
788  }
789 }
790 #endif
791 
792 #if defined(SOL_SOCKET) && defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
793 #if defined(__OpenBSD__)
794 #define RUBY_SOCK_PEERCRED struct sockpeercred
795 #else
796 #define RUBY_SOCK_PEERCRED struct ucred
797 #endif
798 static int
799 inspect_peercred(int level, int optname, VALUE data, VALUE ret)
800 {
801  if (RSTRING_LEN(data) == sizeof(RUBY_SOCK_PEERCRED)) {
802  RUBY_SOCK_PEERCRED cred;
803  memcpy(&cred, RSTRING_PTR(data), sizeof(RUBY_SOCK_PEERCRED));
804  rb_str_catf(ret, " pid=%u euid=%u egid=%u",
805  (unsigned)cred.pid, (unsigned)cred.uid, (unsigned)cred.gid);
806  rb_str_cat2(ret, " (ucred)");
807  return 1;
808  }
809  else {
810  return 0;
811  }
812 }
813 #endif
814 
815 #if defined(LOCAL_PEERCRED) /* FreeBSD, MacOS X */
816 static int
817 inspect_local_peercred(int level, int optname, VALUE data, VALUE ret)
818 {
819  if (RSTRING_LEN(data) == sizeof(struct xucred)) {
820  struct xucred cred;
821  memcpy(&cred, RSTRING_PTR(data), sizeof(struct xucred));
822  if (cred.cr_version != XUCRED_VERSION)
823  return 0;
824  rb_str_catf(ret, " version=%u", cred.cr_version);
825  rb_str_catf(ret, " euid=%u", cred.cr_uid);
826  if (cred.cr_ngroups) {
827  int i;
828  const char *sep = " groups=";
829  for (i = 0; i < cred.cr_ngroups; i++) {
830  rb_str_catf(ret, "%s%u", sep, cred.cr_groups[i]);
831  sep = ",";
832  }
833  }
834  rb_str_cat2(ret, " (xucred)");
835  return 1;
836  }
837  else {
838  return 0;
839  }
840 }
841 #endif
842 
843 
844 /*
845  * call-seq:
846  * sockopt.inspect => string
847  *
848  * Returns a string which shows sockopt in human-readable form.
849  *
850  * p Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i")).inspect
851  * #=> "#<Socket::Option: INET SOCKET KEEPALIVE 1>"
852  *
853  */
854 static VALUE
856 {
857  int family = NUM2INT(sockopt_family_m(self));
858  int level = NUM2INT(sockopt_level_m(self));
859  int optname = NUM2INT(sockopt_optname_m(self));
860  VALUE data = sockopt_data(self);
861  VALUE v, ret;
862  ID family_id, level_id, optname_id;
863  int inspected;
864 
865  StringValue(data);
866 
867  ret = rb_sprintf("#<%s:", rb_obj_classname(self));
868 
869  family_id = rsock_intern_family_noprefix(family);
870  if (family_id)
871  rb_str_catf(ret, " %s", rb_id2name(family_id));
872  else
873  rb_str_catf(ret, " family:%d", family);
874 
875  if (level == SOL_SOCKET) {
876  rb_str_cat2(ret, " SOCKET");
877 
878  optname_id = rsock_intern_so_optname(optname);
879  if (optname_id)
880  rb_str_catf(ret, " %s", rb_id2name(optname_id));
881  else
882  rb_str_catf(ret, " optname:%d", optname);
883  }
884 #ifdef HAVE_SYS_UN_H
885  else if (family == AF_UNIX) {
886  rb_str_catf(ret, " level:%d", level);
887 
888  optname_id = rsock_intern_local_optname(optname);
889  if (optname_id)
890  rb_str_catf(ret, " %s", rb_id2name(optname_id));
891  else
892  rb_str_catf(ret, " optname:%d", optname);
893  }
894 #endif
895  else if (IS_IP_FAMILY(family)) {
896  level_id = rsock_intern_iplevel(level);
897  if (level_id)
898  rb_str_catf(ret, " %s", rb_id2name(level_id));
899  else
900  rb_str_catf(ret, " level:%d", level);
901 
902  v = optname_to_sym(level, optname);
903  if (SYMBOL_P(v))
904  rb_str_catf(ret, " %s", rb_id2name(SYM2ID(v)));
905  else
906  rb_str_catf(ret, " optname:%d", optname);
907  }
908  else {
909  rb_str_catf(ret, " level:%d", level);
910  rb_str_catf(ret, " optname:%d", optname);
911  }
912 
913  inspected = 0;
914 
915  if (level == SOL_SOCKET)
916  family = AF_UNSPEC;
917  switch (family) {
918  case AF_UNSPEC:
919  switch (level) {
920  case SOL_SOCKET:
921  switch (optname) {
922 # if defined(SO_DEBUG) /* POSIX */
923  case SO_DEBUG: inspected = inspect_int(level, optname, data, ret); break;
924 # endif
925 # if defined(SO_ERROR) /* POSIX */
926  case SO_ERROR: inspected = inspect_errno(level, optname, data, ret); break;
927 # endif
928 # if defined(SO_TYPE) /* POSIX */
929  case SO_TYPE: inspected = inspect_socktype(level, optname, data, ret); break;
930 # endif
931 # if defined(SO_ACCEPTCONN) /* POSIX */
932  case SO_ACCEPTCONN: inspected = inspect_int(level, optname, data, ret); break;
933 # endif
934 # if defined(SO_BROADCAST) /* POSIX */
935  case SO_BROADCAST: inspected = inspect_int(level, optname, data, ret); break;
936 # endif
937 # if defined(SO_REUSEADDR) /* POSIX */
938  case SO_REUSEADDR: inspected = inspect_int(level, optname, data, ret); break;
939 # endif
940 # if defined(SO_KEEPALIVE) /* POSIX */
941  case SO_KEEPALIVE: inspected = inspect_int(level, optname, data, ret); break;
942 # endif
943 # if defined(SO_OOBINLINE) /* POSIX */
944  case SO_OOBINLINE: inspected = inspect_int(level, optname, data, ret); break;
945 # endif
946 # if defined(SO_SNDBUF) /* POSIX */
947  case SO_SNDBUF: inspected = inspect_int(level, optname, data, ret); break;
948 # endif
949 # if defined(SO_RCVBUF) /* POSIX */
950  case SO_RCVBUF: inspected = inspect_int(level, optname, data, ret); break;
951 # endif
952 # if defined(SO_DONTROUTE) /* POSIX */
953  case SO_DONTROUTE: inspected = inspect_int(level, optname, data, ret); break;
954 # endif
955 # if defined(SO_RCVLOWAT) /* POSIX */
956  case SO_RCVLOWAT: inspected = inspect_int(level, optname, data, ret); break;
957 # endif
958 # if defined(SO_SNDLOWAT) /* POSIX */
959  case SO_SNDLOWAT: inspected = inspect_int(level, optname, data, ret); break;
960 # endif
961 # if defined(SO_LINGER) /* POSIX */
962  case SO_LINGER: inspected = inspect_linger(level, optname, data, ret); break;
963 # endif
964 # if defined(SO_RCVTIMEO) /* POSIX */
965  case SO_RCVTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
966 # endif
967 # if defined(SO_SNDTIMEO) /* POSIX */
968  case SO_SNDTIMEO: inspected = inspect_timeval_as_interval(level, optname, data, ret); break;
969 # endif
970 # if defined(SO_PEERCRED) /* GNU/Linux, OpenBSD */
971  case SO_PEERCRED: inspected = inspect_peercred(level, optname, data, ret); break;
972 # endif
973  }
974  break;
975  }
976  break;
977 
978  case AF_INET:
979 #ifdef INET6
980  case AF_INET6:
981 #endif
982  switch (level) {
983 # if defined(IPPROTO_IP)
984  case IPPROTO_IP:
985  switch (optname) {
986 # if defined(IP_MULTICAST_IF) && defined(HAVE_TYPE_STRUCT_IP_MREQN) /* 4.4BSD, GNU/Linux */
987  case IP_MULTICAST_IF: inspected = inspect_ipv4_multicast_if(level, optname, data, ret); break;
988 # endif
989 # if defined(IP_ADD_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
990  case IP_ADD_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
991 # endif
992 # if defined(IP_DROP_MEMBERSHIP) /* 4.4BSD, GNU/Linux */
993  case IP_DROP_MEMBERSHIP: inspected = inspect_ipv4_add_drop_membership(level, optname, data, ret); break;
994 # endif
995 # if defined(IP_MULTICAST_LOOP) /* 4.4BSD, GNU/Linux */
996  case IP_MULTICAST_LOOP: inspected = inspect_ipv4_multicast_loop(level, optname, data, ret); break;
997 # endif
998 # if defined(IP_MULTICAST_TTL) /* 4.4BSD, GNU/Linux */
999  case IP_MULTICAST_TTL: inspected = inspect_ipv4_multicast_ttl(level, optname, data, ret); break;
1000 # endif
1001  }
1002  break;
1003 # endif
1004 
1005 # if defined(IPPROTO_IPV6)
1006  case IPPROTO_IPV6:
1007  switch (optname) {
1008 # if defined(IPV6_MULTICAST_HOPS) /* POSIX */
1009  case IPV6_MULTICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
1010 # endif
1011 # if defined(IPV6_MULTICAST_IF) /* POSIX */
1012  case IPV6_MULTICAST_IF: inspected = inspect_ipv6_multicast_if(level, optname, data, ret); break;
1013 # endif
1014 # if defined(IPV6_MULTICAST_LOOP) /* POSIX */
1015  case IPV6_MULTICAST_LOOP: inspected = inspect_uint(level, optname, data, ret); break;
1016 # endif
1017 # if defined(IPV6_JOIN_GROUP) /* POSIX */
1018  case IPV6_JOIN_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
1019 # endif
1020 # if defined(IPV6_LEAVE_GROUP) /* POSIX */
1021  case IPV6_LEAVE_GROUP: inspected = inspect_ipv6_mreq(level, optname, data, ret); break;
1022 # endif
1023 # if defined(IPV6_UNICAST_HOPS) /* POSIX */
1024  case IPV6_UNICAST_HOPS: inspected = inspect_int(level, optname, data, ret); break;
1025 # endif
1026 # if defined(IPV6_V6ONLY) /* POSIX */
1027  case IPV6_V6ONLY: inspected = inspect_int(level, optname, data, ret); break;
1028 # endif
1029  }
1030  break;
1031 # endif
1032 
1033 # if defined(IPPROTO_TCP)
1034  case IPPROTO_TCP:
1035  switch (optname) {
1036 # if defined(TCP_NODELAY) /* POSIX */
1037  case TCP_NODELAY: inspected = inspect_int(level, optname, data, ret); break;
1038 # endif
1039  }
1040  break;
1041 # endif
1042  }
1043  break;
1044 
1045 #ifdef HAVE_SYS_UN_H
1046  case AF_UNIX:
1047  switch (level) {
1048  case 0:
1049  switch (optname) {
1050 # if defined(LOCAL_PEERCRED)
1051  case LOCAL_PEERCRED: inspected = inspect_local_peercred(level, optname, data, ret); break;
1052 # endif
1053  }
1054  break;
1055  }
1056  break;
1057 #endif
1058  }
1059 
1060  if (!inspected) {
1061  rb_str_cat2(ret, " ");
1062  rb_str_append(ret, rb_str_dump(data));
1063  }
1064 
1065  rb_str_cat2(ret, ">");
1066 
1067  return ret;
1068 }
1069 
1070 /*
1071  * call-seq:
1072  * sockopt.unpack(template) => array
1073  *
1074  * Calls String#unpack on sockopt.data.
1075  *
1076  * sockopt = Socket::Option.new(:INET, :SOCKET, :KEEPALIVE, [1].pack("i"))
1077  * p sockopt.unpack("i") #=> [1]
1078  * p sockopt.data.unpack("i") #=> [1]
1079  */
1080 static VALUE
1081 sockopt_unpack(VALUE self, VALUE template)
1082 {
1083  return rb_funcall(sockopt_data(self), rb_intern("unpack"), 1, template);
1084 }
1085 
1086 void
1088 {
1089  /*
1090  * Document-class: Socket::Option
1091  *
1092  * Socket::Option represents a socket option used by
1093  * BasicSocket#getsockopt and BasicSocket#setsockopt. A socket option
1094  * contains the socket #family, protocol #level, option name #optname and
1095  * option value #data.
1096  */
1098  rb_define_method(rb_cSockOpt, "initialize", sockopt_initialize, 4);
1104 
1107 
1110 
1113 
1116 
1118  rb_define_method(rb_cSockOpt, "ipv4_multicast_ttl", sockopt_ipv4_multicast_ttl, 0);
1119 
1121  rb_define_method(rb_cSockOpt, "ipv4_multicast_loop", sockopt_ipv4_multicast_loop, 0);
1122 
1124 
1125  rb_define_method(rb_cSockOpt, "to_s", sockopt_data, 0); /* compatibility for ruby before 1.9.2 */
1126 }
1127 
#define T_OBJECT
Definition: ruby.h:477
ID rsock_intern_family_noprefix(int val)
Definition: constdefs.c:6151
static VALUE sockopt_unpack(VALUE self, VALUE template)
Definition: option.c:1081
#define INT2NUM(x)
Definition: ruby.h:1288
static VALUE sockopt_family_m(VALUE self)
Definition: option.c:80
#define NUM2INT(x)
Definition: ruby.h:630
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:1655
#define Qtrue
Definition: ruby.h:426
static int rb_if_indextoname(const char *succ_prefix, const char *fail_prefix, unsigned int ifindex, char *buf, size_t len)
Definition: option.c:648
#define INET_ADDRSTRLEN
Definition: constdefs.h:1680
const int id
Definition: nkf.c:209
static VALUE sockopt_inspect(VALUE self)
Definition: option.c:855
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:573
#define SYM2ID(x)
Definition: ruby.h:356
static VALUE sockopt_linger(VALUE self)
Definition: option.c:318
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:775
ID rsock_intern_so_optname(int val)
Definition: constdefs.c:6196
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:676
VALUE rb_to_int(VALUE)
Definition: object.c:2679
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1857
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2665
const char * rb_obj_classname(VALUE)
Definition: variable.c:406
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:694
#define IPPROTO_TCP
Definition: constdefs.h:610
static VALUE sockopt_level_m(VALUE self)
Definition: option.c:101
#define INET6_ADDRSTRLEN
Definition: constdefs.h:1687
static VALUE sockopt_ipv4_multicast_ttl(VALUE self)
Definition: option.c:445
static VALUE sockopt_data(VALUE self)
Definition: option.c:138
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
#define level
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
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
static int inspect_errno(int level, int optname, VALUE data, VALUE ret)
Definition: option.c:499
static VALUE sockopt_s_bool(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vbool)
Definition: option.c:249
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
#define snprintf
Definition: subst.h:6
#define NIL_P(v)
Definition: ruby.h:438
int rsock_level_arg(int family, VALUE level)
Definition: constants.c:57
#define inspect_ipv4_multicast_loop(a, b, c, d)
Definition: option.c:404
#define IPPROTO_UDP
Definition: constdefs.h:627
#define Qfalse
Definition: ruby.h:425
int err
Definition: win32.c:114
VALUE rb_cSocket
Definition: init.c:22
static VALUE constant_to_sym(int constant, ID(*intern_const)(int))
Definition: option.c:6
#define IS_IP_FAMILY(af)
Definition: rubysocket.h:154
#define RSTRING_LEN(str)
Definition: ruby.h:841
static int sockopt_optname(VALUE self)
Definition: option.c:107
int socklen_t
Definition: getaddrinfo.c:84
ID rsock_intern_iplevel(int val)
Definition: constdefs.c:6187
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 NUM2CHR(x)
Definition: ruby.h:1329
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:616
unsigned long ID
Definition: ruby.h:89
static const char * inet_ntop(int af, const void *addr, char *numaddr, size_t numaddr_len)
Definition: option.c:628
ID rsock_intern_tcp_optname(int val)
Definition: constdefs.c:6223
unsigned long VALUE
Definition: ruby.h:88
ID rsock_intern_local_optname(int val)
Definition: constdefs.c:6250
static VALUE sockopt_ipv4_multicast_loop(VALUE self)
Definition: option.c:382
ID rsock_intern_socktype(int val)
Definition: constdefs.c:6169
VALUE rb_str_dump(VALUE)
Definition: string.c:4899
static VALUE sockopt_optname_m(VALUE self)
Definition: option.c:122
#define RSTRING_PTR(str)
Definition: ruby.h:845
static int inspect_int(int level, int optname, VALUE data, VALUE ret)
Definition: option.c:471
static VALUE sockopt_int(VALUE self)
Definition: option.c:222
static VALUE sockopt_s_int(VALUE klass, VALUE vfamily, VALUE vlevel, VALUE voptname, VALUE vint)
Definition: option.c:201
#define CHR2FIX(x)
Definition: ruby.h:1331
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1290
static VALUE sockopt_s_ipv4_multicast_loop(VALUE klass, VALUE value)
Definition: option.c:357
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
#define RTEST(v)
Definition: ruby.h:437
#define AF_UNSPEC
Definition: sockport.h:101
ID rsock_intern_udp_optname(int val)
Definition: constdefs.c:6232
static VALUE sockopt_s_linger(VALUE klass, VALUE vonoff, VALUE vsecs)
Definition: option.c:295
int rsock_optname_arg(int family, int level, VALUE optname)
Definition: constants.c:69
VALUE rb_cSockOpt
Definition: option.c:3
const char * name
Definition: nkf.c:208
#define ID2SYM(x)
Definition: ruby.h:355
const char * rb_id2name(ID id)
Definition: ripper.c:17230
static int sockopt_level(VALUE self)
Definition: option.c:86
Definition: ruby.h:762
#define IFNAMSIZ
void rsock_init_sockopt(void)
Definition: option.c:1087
#define inspect_ipv4_multicast_ttl(a, b, c, d)
Definition: option.c:467
#define IPPROTO_IP
Definition: constdefs.h:586
static VALUE sockopt_byte(VALUE self)
Definition: option.c:178
static VALUE sockopt_s_ipv4_multicast_ttl(VALUE klass, VALUE value)
Definition: option.c:420
ID rsock_intern_ipv6_optname(int val)
Definition: constdefs.c:6214
#define rb_intern(str)
#define SYMBOL_P(x)
Definition: ruby.h:354
#define NULL
Definition: _sdbm.c:103
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1488
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2298
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1127
#define StringValue(v)
Definition: ruby.h:539
ID rsock_intern_ip_optname(int val)
Definition: constdefs.c:6205
VALUE rb_str_new(const char *, long)
Definition: string.c:534