事の発端
Windows 7 で IP層のフラグ Don't Fragmentation を OFF にしたいと思い。以下のように設定。
require 'socket'
s0 = TCPServer.open("", 12345)
p s0.setsockopt(:IP, Socket::IP_DONTFRAG, 0) # => uninitialized constant Socket::IP_DONTFRAG (NameError)
Socket::IP_TTL
はうまくいくので、指定が間違っているのではなさそう。
p s0.setsockopt(:IP, Socket::IP_TTL, 255) # => 0
定数が本当にないのか?
require 'socket'
require 'pp'
pp Socket.constants # => [
:Option,
:Constants,
:SOCK_STREAM,
:SOCK_DGRAM,
:SOCK_RAW,
:SOCK_RDM,
:SOCK_SEQPACKET,
:AF_UNSPEC,
:PF_UNSPEC,
:AF_INET,
:PF_INET,
:AF_INET6,
:PF_INET6,
:AF_UNIX,
:PF_UNIX,
:AF_IPX,
:PF_IPX,
:AF_APPLETALK,
:PF_APPLETALK,
:AF_IMPLINK,
:PF_IMPLINK,
:AF_PUP,
:PF_PUP,
:AF_CHAOS,
:PF_CHAOS,
:AF_NS,
:PF_NS,
:AF_ISO,
:PF_ISO,
:AF_OSI,
:PF_OSI,
:AF_ECMA,
:PF_ECMA,
:AF_DATAKIT,
:PF_DATAKIT,
:AF_CCITT,
:PF_CCITT,
:AF_SNA,
:PF_SNA,
:AF_DLI,
:PF_DLI,
:AF_LAT,
:PF_LAT,
:AF_HYLINK,
:PF_HYLINK,
:AF_NETBIOS,
:AF_ATM,
:PF_ATM,
:AF_MAX,
:PF_MAX,
:MSG_OOB,
:MSG_PEEK,
:MSG_DONTROUTE,
:MSG_WAITALL,
:SOL_SOCKET,
:IPPROTO_IP,
:IPPROTO_ICMP,
:IPPROTO_IGMP,
:IPPROTO_GGP,
:IPPROTO_TCP,
:IPPROTO_PUP,
:IPPROTO_UDP,
:IPPROTO_IDP,
:IPPROTO_ND,
:IPPROTO_AH,
:IPPROTO_DSTOPTS,
:IPPROTO_ESP,
:IPPROTO_FRAGMENT,
:IPPROTO_HOPOPTS,
:IPPROTO_ICMPV6,
:IPPROTO_IPV6,
:IPPROTO_NONE,
:IPPROTO_ROUTING,
:IPPROTO_RAW,
:IPPROTO_MAX,
:IPPORT_RESERVED,
:IPPORT_USERRESERVED,
:INADDR_ANY,
:INADDR_BROADCAST,
:INADDR_LOOPBACK,
:INADDR_UNSPEC_GROUP,
:INADDR_ALLHOSTS_GROUP,
:INADDR_MAX_LOCAL_GROUP,
:INADDR_NONE,
:IP_OPTIONS,
:IP_HDRINCL,
:IP_TOS,
:IP_TTL,
:IP_MULTICAST_IF,
:IP_MULTICAST_TTL,
:IP_MULTICAST_LOOP,
:IP_ADD_MEMBERSHIP,
:IP_DROP_MEMBERSHIP,
:IP_PKTINFO,
:IP_UNBLOCK_SOURCE,
:IP_BLOCK_SOURCE,
:IP_ADD_SOURCE_MEMBERSHIP,
:IP_DROP_SOURCE_MEMBERSHIP,
:SO_DEBUG,
:SO_REUSEADDR,
:SO_TYPE,
:SO_ERROR,
:SO_DONTROUTE,
:SO_BROADCAST,
:SO_SNDBUF,
:SO_RCVBUF,
:SO_KEEPALIVE,
:SO_OOBINLINE,
:SO_LINGER,
:SO_RCVLOWAT,
:SO_SNDLOWAT,
:SO_RCVTIMEO,
:SO_SNDTIMEO,
:SO_ACCEPTCONN,
:SO_USELOOPBACK,
:TCP_NODELAY,
:EAI_AGAIN,
:EAI_BADFLAGS,
:EAI_FAIL,
:EAI_FAMILY,
:EAI_MEMORY,
:EAI_NODATA,
:EAI_NONAME,
:EAI_SERVICE,
:EAI_SOCKTYPE,
:AI_PASSIVE,
:AI_CANONNAME,
:AI_NUMERICHOST,
:NI_MAXHOST,
:NI_MAXSERV,
:NI_NOFQDN,
:NI_NUMERICHOST,
:NI_NAMEREQD,
:NI_NUMERICSERV,
:NI_DGRAM,
:SHUT_RD,
:SHUT_WR,
:SHUT_RDWR,
:IPV6_JOIN_GROUP,
:IPV6_LEAVE_GROUP,
:IPV6_MULTICAST_HOPS,
:IPV6_MULTICAST_IF,
:IPV6_MULTICAST_LOOP,
:IPV6_UNICAST_HOPS,
:IPV6_HOPLIMIT,
:IPV6_PKTINFO,
:INET_ADDRSTRLEN,
:INET6_ADDRSTRLEN,
:SOMAXCONN,
:UDPSource,
:WaitReadable,
:WaitWritable,
:SEEK_SET,
:SEEK_CUR,
:SEEK_END,
:RDONLY,
:WRONLY,
:RDWR,
:APPEND,
:CREAT,
:EXCL,
:NONBLOCK,
:TRUNC,
:BINARY,
:LOCK_SH,
:LOCK_EX,
:LOCK_UN,
:LOCK_NB,
:NULL,
:FNM_NOESCAPE,
:FNM_PATHNAME,
:FNM_DOTMATCH,
:FNM_CASEFOLD,
:FNM_EXTGLOB,
:FNM_SYSCASE]
... ない。何故ないのかは不明。
setsockopt に Integer 直接入れたら行けんじゃね?
rubyのリファレンスのSocket#setsockopt
を見てみると。
setsockopt(2)を参照してくださいとの記載が。見ると、引数はint
の模様。
rubyから整数を渡してやったらそのまま設定されるんじゃないか説浮上。
Windows の Don't Fragment 定数値
MSDNに記載あり。https://msdn.microsoft.com/ja-jp/library/windows/desktop/ms738586(v=vs.85).aspx
IP_DONT_FRAGMENT
がそれっぽい。定義はWinsock2.h
を見ろと。ふむふむ。
色々検索してサイトを渡り歩いていると以下のサイトに出会う。
なんか不穏なことが書いてあるけど、9か14を使えばいいのね。
ruby は ws2tcpip.h を使っている。
9か14を使えってのはわかったけど、どっち使うか。
ruby の github リポジトリを眺めてると ws2tcpip.h
を使ってたので、14が正解。
https://github.com/ruby/ruby/blob/f150a381db5b51552b714e9a5893654cd056962c/include/ruby/win32.h#L42
setsockopt に Integer を直接入れてみる。
require 'socket'
s0 = TCPServer.open("", 12345)
p s0.setsockopt(:IP, 14, 0) # => 0
いけたっぽい?