Skip to content

Instantly share code, notes, and snippets.

@rickhull
Last active January 17, 2023 01:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rickhull/d027f4d620d2efdc160af91d6560da0d to your computer and use it in GitHub Desktop.
Save rickhull/d027f4d620d2efdc160af91d6560da0d to your computer and use it in GitHub Desktop.
What are the available Unix Socket types in Ruby (on Linux)?
best [:SOCK_STREAM, :SOCK_DGRAM, :SOCK_SEQPACKET]
:SOCK_STREAM TYPE SOCK_STREAM
:SOCK_DGRAM TYPE SOCK_DGRAM
:SOCK_SEQPACKET TYPE SOCK_SEQPACKET
other [nil, :SOCK_RAW]
nil TYPE SOCK_STREAM
:SOCK_RAW TYPE SOCK_DGRAM
unsupported [:SOCK_RDM, :SOCK_PACKET, :SOCK_NONBLOCK, :SOCK_CLOEXEC]
:SOCK_RDM Errno::ESOCKTNOSUPPORT
:SOCK_PACKET Errno::ESOCKTNOSUPPORT
:SOCK_NONBLOCK Errno::ESOCKTNOSUPPORT
:SOCK_CLOEXEC Errno::ESOCKTNOSUPPORT
invalid [:RAW_SOCK]
:RAW_SOCK SocketError
1 DEBUG 0
2 REUSEADDR 0
3 TYPE SOCK_STREAM
4 ERROR Success (0)
5 DONTROUTE 0
6 BROADCAST 0
7 SNDBUF 212992
8 RCVBUF 212992
9 KEEPALIVE 0
10 OOBINLINE 0
11 NO_CHECK "\x00\x00\x00\x00"
12 PRIORITY "\x00\x00\x00\x00"
13 LINGER off 0sec
14 optname:14 "\x00\x00\x00\x00"
15 REUSEPORT "\x00\x00\x00\x00"
16 PASSCRED "\x00\x00\x00\x00"
17 PEERCRED pid=143083 euid=1000 egid=100 (ucred)
18 RCVLOWAT 1
19 SNDLOWAT 1
20 RCVTIMEO 0.000000sec
21 SNDTIMEO 0.000000sec
25 BINDTODEVICE ""
26 ATTACH_FILTER ""
29 TIMESTAMP "\x00\x00\x00\x00"
30 ACCEPTCONN 0
31 PEERSEC "kernel\x00"
34 PASSSEC "\x00\x00\x00\x00"
35 TIMESTAMPNS "\x00\x00\x00\x00"
36 MARK "\x00\x00\x00\x00"
37 TIMESTAMPING "\x00\x00\x00\x00\x00\x00\x00\x00"
38 PROTOCOL "\x00\x00\x00\x00"
39 DOMAIN "\x01\x00\x00\x00"
40 RXQ_OVFL "\x00\x00\x00\x00"
41 WIFI_STATUS "\x00\x00\x00\x00"
42 PEEK_OFF "\xFF\xFF\xFF\xFF"
43 NOFCS "\x00\x00\x00\x00"
44 LOCK_FILTER "\x00\x00\x00\x00"
45 SELECT_ERR_QUEUE "\x00\x00\x00\x00"
46 BUSY_POLL "\x00\x00\x00\x00"
47 MAX_PACING_RATE "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
48 BPF_EXTENSIONS "@\x00\x00\x00"
49 optname:49 "\xFF\xFF\xFF\xFF"
55 optname:55 "\x00\x00\x00\x00\x00@\x03\x00\x00\x00\x00\x00\x00@\x03\x00\x00\x00\x00\x00\x00\x00\x00
56 optname:56 "\x00\x00\x00\x00"
57 optname:57 "2\x10\x00\x00\x00\x00\x00\x00"
59 optname:59 "\x01\x00\x00\x00d\x00\x00\x00\xE3\x03\x00\x00"
60 optname:60 "\x00\x00\x00\x00"
61 optname:61 "\x00\x00\x00\x00\x00\x00\x00\x00"
62 optname:62 "\x00\x00\x00\x00"
63 optname:63 "\x00\x00\x00\x00"
64 optname:64 "\x00\x00\x00\x00"
66 optname:66 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
67 optname:67 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
69 optname:69 "\x00\x00\x00\x00"
72 optname:72 "\x00\x00\x00\x00"
check DGRAM sockopts against RAW sockopts
value mismatch: [57]: "optname:57 \"3\\x10\\x00\\x00\\x00\\x00\\x00\\x00\"" "optname:57 \"5\\x10\\x00\\x00\\x00\\x00\\x00\\x00\""
DONE
# NOTE: these are _Unix_ sockets, not network sockets
require 'socket'
# get the level 1 socket option for num
def get_opt sock, num
sock.getsockopt(1, num)
end
# a short readable string version of the socket option
def string_opt sock, num
get_opt(sock, num).inspect[30, 99].chop
end
# get the socket type, option number 3
def get_type sock
string_opt sock, Socket::SO_TYPE # 3
end
# return an array of strings
def brute_sockopts sock
ary = []
99.times { |i|
begin
str = string_opt(sock, i)
rescue Errno::ENOPROTOOPT, Errno::EINVAL
next
end
ary[i] = str
}
ary
end
# man page for unix sockets:
# SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET
# let's try:
socktypes = {
best: [:SOCK_STREAM, :SOCK_DGRAM, :SOCK_SEQPACKET],
other: [nil, :SOCK_RAW],
unsupported: [:SOCK_RDM, :SOCK_PACKET, :SOCK_NONBLOCK, :SOCK_CLOEXEC],
invalid: [:RAW_SOCK],
}
socktypes.each { |group, types|
puts [group, types.inspect].join("\t")
types.each { |type|
if type.nil?
a, b = UNIXSocket.pair
else
begin
a, b = UNIXSocket.pair(type)
rescue StandardError => e
puts [type.inspect, e.class].join("\t")
next
end
end
puts [type.inspect, get_type(a)].join("\t")
a.close; b.close
}
puts
}
sock_stream, other_stream = UNIXSocket.pair(:SOCK_STREAM)
other_stream.close
opts_stream = brute_sockopts(sock_stream)
puts opts_stream.map.with_index { |val, idx|
val and [idx, val].join("\t")
}.compact.join("\n")
sock_dgram, other_dgram = UNIXSocket.pair(:DGRAM)
other_dgram.close
opts_dgram = brute_sockopts(sock_dgram)
sock_nil, other_nil = UNIXSocket.pair
other_nil.close
opts_nil = brute_sockopts(sock_nil)
sock_raw, other_raw = UNIXSocket.pair(:RAW)
other_raw.close
opts_raw = brute_sockopts(sock_raw)
puts
puts "check DGRAM sockopts against RAW sockopts"
opts_dgram.each.with_index { |val, idx|
other = opts_raw[idx]
if val.class != other.class
puts format("class mismatch: [%i]: %s %s", idx, val.class, other.class)
end
if val != other
puts format("value mismatch: [%i]: %s %s", idx, val.inspect, other.inspect)
end
}
puts "DONE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment