Class: Netlink::Socket

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/netlink/socket.rb

Overview

Handle a netlink socket

Constant Summary collapse

16
DEFAULT_BUFFER_SIZE =

Default buffer size

32 * 1024

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(family) ⇒ Socket

Returns a new instance of Socket.

Parameters:

  • family (Integer)

    Netlink family



54
55
56
57
58
59
60
61
# File 'lib/netlink/socket.rb', line 54

def initialize(family)
  @family = family
  @pid = self.class.generate_pid
  @socket = ::Socket.new(AF_NETLINK, ::Socket::SOCK_RAW, family)
  @seqnum = 1
  @default_buffer_size = DEFAULT_BUFFER_SIZE
  @groups = 0
end

Class Method Details

.generate_pidInteger

Generate a Port Id from Process Id (on 22 bits) and a counter (on 10 bits)

Returns:

  • (Integer)


21
22
23
24
25
26
27
# File 'lib/netlink/socket.rb', line 21

def generate_pid
  @next_pid = Process.pid << 10 unless defined? @next_pid

  pid = @next_pid
  @next_pid += 1
  pid
end

.new(family) ⇒ Object Also known as: open



31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/netlink/socket.rb', line 31

def new(family)
  sock = old_new(family)
  if block_given?
    begin
      yield sock
    ensure
      sock.close
    end
  else
    sock
  end
end

.old_newObject



29
# File 'lib/netlink/socket.rb', line 29

alias old_new new

.sockaddr_nl(pid, groups) ⇒ Object

Pack pid and groups as a AF_NETLINK sockaddr string.

Parameters:

  • pid (Integer)
  • groups (Integer)


48
49
50
# File 'lib/netlink/socket.rb', line 48

def sockaddr_nl(pid, groups)
  [AF_NETLINK, 0, pid, groups].pack('SSLL')
end

Instance Method Details

#addrArray(String, Integer, Integer)

Returns First element is the socket family name, second is the socket’s pid and the third, the groups.

Returns:

  • (Array(String, Integer, Integer))

    First element is the socket family name, second is the socket’s pid and the third, the groups



64
65
66
# File 'lib/netlink/socket.rb', line 64

def addr
  ['AF_NETLINK', @pid, @groups]
end

#bind(groups) ⇒ 0

Binds a socket to its pid and to given groups

Parameters:

  • groups (Integer)

Returns:

  • (0)

Raises:

  • (Errno)


77
78
79
80
81
# File 'lib/netlink/socket.rb', line 77

def bind(groups)
  @groups = groups
  sockaddr = self.class.sockaddr_nl(@pid, groups)
  @socket.bind(sockaddr)
end

#inspectString

Returns:

  • (String)


69
70
71
# File 'lib/netlink/socket.rb', line 69

def inspect
  "#<#{self.class}:fd #{@socket.fileno}, AF_NETLINK, #{@family}, #{@pid}>"
end

#recvmsg(maxmesglen = nil, flags = 0) ⇒ Array(String, Addrinfo, Integer, NlMsgHdr)

Receive a message

Parameters:

  • maxmesglen (Integer) (defaults to: nil)

    maximum number of bytes to receive as message

  • flags (Integer) (defaults to: 0)

    flags should be a bitwise OR of Socket::MSG_* constants

Returns:

  • (Array(String, Addrinfo, Integer, NlMsgHdr))

    [mesg, sender_addrinfo, rflags, controls] where:

    • mesg is the message as a String or a NlMsgError,

    • sender_addrinfo is a Addrinfo about sender,

    + controls is the ancillary data, here the header of message as a NlMsgHdr.

Raises:

  • (NlmsgError)


103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/netlink/socket.rb', line 103

def recvmsg(maxmesglen=nil, flags=0)
  maxmesglen ||= @default_buffer_size
  maxlen = maxmesglen + NlMsgHdr::SIZE
  mesg, sender_ai, = @socket.recvmsg(maxlen, flags)
  hdr = NlMsgHdr.from_string(mesg.slice!(0, NlMsgHdr::SIZE))
  if hdr.type == NLMSG_ERROR
    mesg = NlMsgError.from_string(mesg)
    raise Error, "Error #{mesg.error_code} for message with seq #{mesg.orig_header.seq} from pid #{mesg.orig_header.pid}" unless mesg.ack?
  end

  mesg = mesg[0, maxmesglen] if mesg.is_a?(String)
  [mesg, Addrinfo.new(sender_ai.to_sockaddr), hdr]
end

#sendmsg(mesg, nlm_type, nlm_flags = 0, flags = 0, dest_sockaddr = nil) ⇒ Integer

Send mesg via socket

Parameters:

  • mesg (String)

    message to send

  • nlm_type (Integer)

    Message Type

  • nlm_flags (Integer) (defaults to: 0)

    Netlink message flags. Should be a bitwise OR of Netlink::NLM_F_* constants

  • flags (Integer) (defaults to: 0)

    flags Socket flags. Should be a bitwise OR of Socket::MSG_* constants

  • dest_sockaddr (String, Addrinfo, nil) (defaults to: nil)

Returns:

  • (Integer)

    number of bytes sent



90
91
92
93
# File 'lib/netlink/socket.rb', line 90

def sendmsg(mesg, nlm_type, nlm_flags=0, flags=0, dest_sockaddr=nil)
  nlmsg = create_nlmsg(mesg, nlm_type, nlm_flags)
  @socket.sendmsg(nlmsg, flags, dest_sockaddr.to_s)
end