dnet-ffi 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/dnet/ip6.rb ADDED
@@ -0,0 +1,59 @@
1
+ module Dnet
2
+ # /*
3
+ # * IPv6 header
4
+ # */
5
+ # struct ip6_hdr {
6
+ # union {
7
+ # struct ip6_hdr_ctl {
8
+ # uint32_t ip6_un1_flow; /* 20 bits of flow ID */
9
+ # uint16_t ip6_un1_plen; /* payload length */
10
+ # uint8_t ip6_un1_nxt; /* next header */
11
+ # uint8_t ip6_un1_hlim; /* hop limit */
12
+ # } ip6_un1;
13
+ # uint8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */
14
+ # } ip6_ctlun;
15
+ # ip6_addr_t ip6_src;
16
+ # ip6_addr_t ip6_dst;
17
+ # } __attribute__((__packed__));
18
+
19
+
20
+ #
21
+ # Preferred extension header order from RFC 2460, 4.1:
22
+ #
23
+ # IP_PROTO_IPV6, IP_PROTO_HOPOPTS, IP_PROTO_DSTOPTS, IP_PROTO_ROUTING,
24
+ # IP_PROTO_FRAGMENT, IP_PROTO_AH, IP_PROTO_ESP, IP_PROTO_DSTOPTS,
25
+ # IP_PROTO_*
26
+ #
27
+
28
+ # /*
29
+ # * Routing header data (IP_PROTO_ROUTING)
30
+ # */
31
+ # struct ip6_ext_data_routing {
32
+ # uint8_t type; /* routing type */
33
+ # uint8_t segleft; /* segments left */
34
+ # /* followed by routing type specific data */
35
+ # } __attribute__((__packed__));
36
+
37
+
38
+ # struct ip6_ext_data_routing0 {
39
+ # uint8_t type; /* always zero */
40
+ # uint8_t segleft; /* segments left */
41
+ # uint8_t reserved; /* reserved field */
42
+ # uint8_t slmap[3]; /* strict/loose bit map */
43
+ # ip6_addr_t addr[1]; /* up to 23 addresses */
44
+ # } __attribute__((__packed__));
45
+
46
+
47
+ # /*
48
+ # * Fragment header data (IP_PROTO_FRAGMENT)
49
+ # */
50
+ # struct ip6_ext_data_fragment {
51
+ # uint16_t offlg; /* offset, reserved, and flag */
52
+ # uint32_t ident; /* identification */
53
+ # } __attribute__((__packed__));
54
+ #
55
+ # void ip6_checksum(void *buf, size_t len);
56
+
57
+ attach_function :ip6_checksum, [:pointer, :size_t], :void
58
+
59
+ end
data/lib/dnet/rand.rb ADDED
@@ -0,0 +1,33 @@
1
+
2
+ ### libdnet's random number generation
3
+
4
+ module Dnet
5
+
6
+ # rand_t * rand_open(void);
7
+ attach_function :rand_open, [], :pointer
8
+
9
+ # int rand_get(rand_t *r, void *buf, size_t len);
10
+ attach_function :rand_get, [:pointer, :string, :size_t], :int
11
+
12
+ # int rand_set(rand_t *r, const void *seed, size_t len);
13
+ attach_function :rand_set, [:pointer, :string, :size_t], :int
14
+
15
+ # int rand_add(rand_t *r, const void *buf, size_t len);
16
+ attach_function :rand_add, [:pointer, :string, :size_t], :int
17
+
18
+ # uint8_t rand_uint8(rand_t *r);
19
+ attach_function :rand_uint8, [:pointer], :uint8
20
+
21
+ # uint16 t rand_uint16(rand_t *r);
22
+ attach_function :rand_uint16, [:pointer], :uint16
23
+
24
+ # uint32_t rand_uint32(rand_t *r);
25
+ attach_function :rand_uint32, [:pointer], :uint32
26
+
27
+ # int rand_shuffle(rand_t *r, void *base, size_t nmemb, size_t size);
28
+ attach_function :rand_shuffle, [:pointer, :string, :size_t, :size_t], :int
29
+
30
+ # rand_t * rand_close(rand_t *r);
31
+ attach_function :rand_close, [:pointer], :pointer
32
+
33
+ end
data/lib/dnet/route.rb ADDED
@@ -0,0 +1,103 @@
1
+
2
+ ### dnet(3) routing interface
3
+
4
+ module Dnet
5
+
6
+ module Route
7
+ # Routing table entry
8
+ #
9
+ # struct route_entry {
10
+ # struct addr route_dst; /* destination address */
11
+ # struct addr route_gw; /* gateway address */
12
+ # };
13
+ class Entry < ::FFI::Struct
14
+ include ::FFI::DRY::StructHelper
15
+
16
+ dsl_layout do
17
+ struct :dst, ::Dnet::Addr, :dest => 'destination gateway'
18
+ struct :gw, ::Dnet::Addr, :dest => 'gateway address'
19
+ end
20
+ end
21
+
22
+ # Obtains a handle to access the kernel route(4) table.
23
+ class Handle < LoopableHandle
24
+ attr_reader :handle
25
+
26
+ # Obtains a handle to access the kernel route(4) table. Uses dnet(3)'s
27
+ # route_open() under the hood.
28
+ def initialize
29
+ if (@handle = ::Dnet.route_open()).address == 0
30
+ raise H_ERR.new("unable to open route handle")
31
+ end
32
+ _handle_opened!
33
+ end
34
+
35
+ # Closes the routing handle handle. Uses dnet(3)'s route_close() under the
36
+ # hood.
37
+ def close
38
+ _do_if_open { _handle_closed! ; ::Dnet.route_close(@fw) }
39
+ end
40
+
41
+ # Iterates over the kernel route(4) table, invoking the specified block
42
+ # with each route cast as a Entry object. Uses dnet(3)'s route_loop()
43
+ # function under the hood.
44
+ def loop &block
45
+ _loop ::Dnet, :route_loop, Entry, &block
46
+ end
47
+
48
+ # Retrieves the routing table entry for the destination 'dst' (supplied as
49
+ # a String argument and parsed via dnet(3)'s addr_aton() function). Uses
50
+ # dnet(3)'s route_get() under the hood.
51
+ def get(dst)
52
+ _check_open!
53
+ re = Entry.new
54
+ if( re.dst.set_string(dst) and ::Dnet.route_get(@handle, re) == 0 )
55
+ return re
56
+ end
57
+ end
58
+
59
+
60
+ # Adds a new routing table entry (supplied as a Entry). Uses dnet(3)'s
61
+ # route_add() under the hood.
62
+ def add(entry)
63
+ _check_open!
64
+ ::Dnet.route_add(@handle, entry)
65
+ end
66
+
67
+ # Delete's the specified route entry for the destination prefix specified
68
+ # by the destination 'dst' (supplied as a String argument and parsed
69
+ # by dnet(3)'s addr_aton function).
70
+ def delete(dst)
71
+ _check_open!
72
+ re = Entry.new
73
+ if( re.dst.set_string(dst) and ::Dnet.route_get(@handle, re) == 0 )
74
+ return re
75
+ end
76
+ end
77
+ end # Handle
78
+
79
+ def self.open(*args)
80
+ Handle.open(*args){|*y| yield(*y) if block_given? }
81
+ end
82
+
83
+ def self.entries
84
+ Handle.entries
85
+ end
86
+
87
+ def self.each_entry(*args)
88
+ Handle.each_entry(*args){|*y| yield(*y) }
89
+ end
90
+ end # Route
91
+
92
+ # just an alias for Route::Handle
93
+ RouteHandle = Route::Handle
94
+
95
+ callback :route_handler, [:route_t, :string], :int
96
+ attach_function :route_open, [], :route_t
97
+ attach_function :route_add, [:route_t, Route::Entry], :int
98
+ attach_function :route_delete, [:route_t, Route::Entry], :int
99
+ attach_function :route_get, [:route_t, Route::Entry], :int
100
+ attach_function :route_loop, [:route_t, :route_handler, :ulong], :int
101
+ attach_function :route_close, [:route_t], :route_t
102
+
103
+ end
data/lib/dnet/tcp.rb ADDED
@@ -0,0 +1,103 @@
1
+ module Dnet
2
+ module Tcp
3
+
4
+ # TCP header, without options
5
+ #
6
+ # field :sport, :uint16, :desc => 'source port'
7
+ # field :dport, :uint16, :desc => 'destination port'
8
+ # field :seq, :uint32, :desc => 'sequence number'
9
+ # field :ack, :uint32, :desc => 'acknowledgment number'
10
+ # field :off_x2, :uint8, :desc => 'data offset(& 0xf0) unused (& 0x0f)'
11
+ # field :flags, :uint8, :desc => 'control flags'
12
+ # field :win, :uint16, :desc => 'window'
13
+ # field :sum, :uint16, :desc => 'checksum'
14
+ # field :urgp, :uint16, :desc => 'urgent pointer'
15
+ #
16
+ class Hdr < ::FFI::Struct
17
+ include ::FFI::DRY::StructHelper
18
+ include ::Dnet::NetEndianHelper
19
+
20
+ dsl_layout do
21
+ field :sport, :uint16, :desc => 'source port'
22
+ field :dport, :uint16, :desc => 'destination port'
23
+ field :seq, :uint32, :desc => 'sequence number'
24
+ field :ack, :uint32, :desc => 'acknowledgment number'
25
+ field :off_x2, :uint8, :desc => 'data offset(& 0xf0) unused (& 0x0f)'
26
+ field :flags, :uint8, :desc => 'control flags'
27
+ field :win, :uint16, :desc => 'window'
28
+ field :sum, :uint16, :desc => 'checksum'
29
+ field :urgp, :uint16, :desc => 'urgent pointer'
30
+ end
31
+
32
+ # TCP control flags (flags)
33
+ module Flags
34
+ include ::FFI::DRY::ConstFlagsMap
35
+ slurp_constants(::Dnet, "TH_")
36
+ def self.list; @@list ||= super() ; end
37
+ end
38
+
39
+ # #define \
40
+ # tcp_pack_hdr(hdr, sport, dport, seq, ack, flags, win, urp) do { \
41
+ # struct tcp_hdr *tcp_pack_p = (struct tcp_hdr *)(hdr); \
42
+ # tcp_pack_p->th_sport = htons(sport); \
43
+ # tcp_pack_p->th_dport = htons(dport); \
44
+ # tcp_pack_p->th_seq = htonl(seq); \
45
+ # tcp_pack_p->th_ack = htonl(ack); \
46
+ # tcp_pack_p->th_x2 = 0; tcp_pack_p->th_off = 5; \
47
+ # tcp_pack_p->th_flags = flags; \
48
+ # tcp_pack_p->th_win = htons(win); \
49
+ # tcp_pack_p->th_urp = htons(urp); \
50
+ # } while (0)
51
+
52
+ end
53
+
54
+ #
55
+ # TCP option (following TCP header)
56
+ #
57
+ # struct tcp_opt {
58
+ # uint8_t opt_type; /* option type */
59
+ # uint8_t opt_len; /* option length >= TCP_OPT_LEN */
60
+ # union tcp_opt_data {
61
+ # uint16_t mss; /* TCP_OPT_MSS */
62
+ # uint8_t wscale; /* TCP_OPT_WSCALE */
63
+ # uint16_t sack[19]; /* TCP_OPT_SACK */
64
+ # uint32_t echo; /* TCP_OPT_ECHO{REPLY} */
65
+ # uint32_t timestamp[2]; /* TCP_OPT_TIMESTAMP */
66
+ # uint32_t cc; /* TCP_OPT_CC{NEW,ECHO} */
67
+ # uint8_t cksum; /* TCP_OPT_ALTSUM */
68
+ # uint8_t md5[16]; /* TCP_OPT_MD5 */
69
+ # uint8_t data8[TCP_OPT_LEN_MAX - TCP_OPT_LEN];
70
+ # } opt_data;
71
+ # } __attribute__((__packed__));
72
+ #
73
+ class Opt < ::FFI::Struct
74
+ include ::FFI::DRY::StructHelper
75
+ include ::Dnet::NetEndianHelper
76
+
77
+ DATA_LEN = TCP_OPT_LEN_MAX - TCP_OPT_LEN
78
+
79
+ dsl_layout do
80
+ field :otype, :uint8
81
+ field :len, :uint8
82
+ array :data8, [:uint8, DATA_LEN]
83
+ end
84
+
85
+ # Options (otype) - http://www.iana.org/assignments/tcp-parameters
86
+ module Otype
87
+ include ::FFI::DRY::ConstMap
88
+ slurp_constants(::Dnet, "TCP_OTYPE_")
89
+ def self.list; @@list ||= super() ; end
90
+ end
91
+
92
+ end # class Opt
93
+
94
+ # TCP FSM states
95
+ module State
96
+ include ::FFI::DRY::ConstMap
97
+ slurp_constants(::Dnet, "TCP_STATE_")
98
+ def self.list; @@list ||= super() ; end
99
+ end
100
+
101
+ end # module Tcp
102
+ end # module Dnet
103
+
data/lib/dnet/tun.rb ADDED
@@ -0,0 +1,24 @@
1
+
2
+ ### libdnet's tunnel interface
3
+
4
+ module Dnet
5
+
6
+ # tun_t * tun_open(struct addr *src, struct addr *dst, int mtu);
7
+ attach_function :tun_open, [:pointer, :pointer, :int], :pointer
8
+
9
+ # int tun_fileno(tun_t *t);
10
+ attach_function :tun_fileno, [:pointer], :int
11
+
12
+ # const char * tun_name(tun_t *t);
13
+ attach_function :tun_name, [:pointer], :string
14
+
15
+ # ssize_t tun_send(tun_t *t, const void *buf, size_t size);
16
+ attach_function :tun_send, [:pointer, :string, :size_t], :ssize_t
17
+
18
+ # ssize_t tun_recv(tun_t *t, void *buf, size_t size);
19
+ attach_function :tun_recv, [:pointer, :string, :size_t], :ssize_t
20
+
21
+ # tun_t * tun_close(tun_t *t);
22
+ attach_function :tun_close, [:pointer], :pointer
23
+
24
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module Dnet
3
+
4
+ typedef :uint32, :ip_addr_t
5
+
6
+ typedef :pointer, :eth_t
7
+ typedef :pointer, :fw_t
8
+ typedef :pointer, :intf_t
9
+ typedef :pointer, :ip_t
10
+ typedef :pointer, :route_t
11
+
12
+ end
data/lib/dnet/udp.rb ADDED
@@ -0,0 +1,31 @@
1
+ module Dnet
2
+
3
+ class Udp
4
+ class Hdr < ::FFI::Struct
5
+ include ::FFI::DRY::StructHelper
6
+ include ::Dnet::NetEndianHelper
7
+
8
+ # struct udp_hdr {
9
+ # uint16_t uh_sport; /* source port */
10
+ # uint16_t uh_dport; /* destination port */
11
+ # uint16_t uh_ulen; /* udp length (including header) */
12
+ # uint16_t uh_sum; /* udp checksum */
13
+ # };
14
+ dsl_layout do
15
+ field :sport, :uint16
16
+ field :dport, :uint16
17
+ field :len, :uint16
18
+ field :sum, :uint16
19
+ end
20
+ end
21
+ end
22
+
23
+
24
+ # #define udp_pack_hdr(hdr, sport, dport, ulen) do { \
25
+ # struct udp_hdr *udp_pack_p = (struct udp_hdr *)(hdr); \
26
+ # udp_pack_p->uh_sport = htons(sport); \
27
+ # udp_pack_p->uh_dport = htons(dport); \
28
+ # udp_pack_p->uh_ulen = htons(ulen); \
29
+ # } while (0)
30
+
31
+ end
data/lib/dnet/util.rb ADDED
@@ -0,0 +1,70 @@
1
+
2
+ module Dnet
3
+ module Util
4
+ RX_IP4_ADDR = /(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/
5
+ RX_MAC_ADDR = /(?:(?:[a-f0-9]{1,2}[:-])?{5}[a-f0-9]{1,2})/i
6
+
7
+ # A number of helper methods which can be used to extend class, instance,
8
+ # or module
9
+ module Helpers
10
+
11
+ def unhexify(str, d=/\s*/)
12
+ str.to_s.strip.gsub(/([A-Fa-f0-9]{1,2})#{d}?/) { $1.hex.chr }
13
+ end
14
+
15
+ # Attempts to derive a memory pointer and length from an "anonymous" object.
16
+ # Returns an an array object containing [len, pointer]
17
+ #
18
+ # buf can be a String or FFI::Pointer. If it is a Pointer, bsz must also
19
+ # be supplied for the length. If bsz is included with a String, the string
20
+ # will be truncated if it is longer.
21
+ #
22
+ # This is mostly used to support multiple argument types in various
23
+ # functions.
24
+ def derive_pointer(buf, bsz=nil)
25
+ case buf
26
+ when ::FFI::Pointer
27
+ raise "no length specified for pointer" if bsz.nil?
28
+ raise "size must be a number >= 0" unless bsz.is_a? Numeric and bsz >= 0
29
+ raise "null pointer #{buf.inspect}" if buf.address == 0
30
+ pbuf = buf
31
+ when String
32
+ buf = buf[0,bsz] if bsz
33
+ pbuf = ::FFI::MemoryPointer.from_string(buf)
34
+ bsz = buf.size
35
+ else
36
+ raise "cannot derive a pointer and size from a #{buf.class}"
37
+ end
38
+ return [pbuf, bsz]
39
+ end
40
+
41
+ # takes a IPv4 number and returns it as a 32-bit number
42
+ def ipv4_atol(str)
43
+ unless str =~ /^#{::Dnet::Util::RX_IP4_ADDR}$/
44
+ raise(::ArgumentError, "invalid IP address #{str.inspect}")
45
+ else
46
+ u32=0
47
+ str.split('.',4).each {|o| u32 = ((u32 << 8) | o.to_i) }
48
+ return u32
49
+ end
50
+ end
51
+
52
+ # takes a 32-bit number and returns it as an IPv4 address string.
53
+ def ipv4_ltoa(int)
54
+ unless(int.is_a? Numeric and int <= 0xffffffff)
55
+ raise(::ArgumentError, "not a long integer: #{int.inspect}")
56
+ end
57
+ ret = []
58
+ 4.times do
59
+ ret.unshift(int & 0xff)
60
+ int >>= 8
61
+ end
62
+ ret.join('.')
63
+ end
64
+
65
+ end # module Helpers
66
+
67
+ extend(::Dnet::Util::Helpers)
68
+ end # module Util
69
+
70
+ end