ruby-ipqueue 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/Rakefile +26 -0
- data/ext/ipqueue/extconf.rb +7 -0
- data/ext/ipqueue/ipqueue.c +208 -0
- data/lib/ipqueuepacket.rb +36 -0
- data/test/test.rb +13 -0
- data/test/test.sh +5 -0
- metadata +56 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/packagetask'
|
|
3
|
+
require 'rake/gempackagetask'
|
|
4
|
+
|
|
5
|
+
PKG_VERSION = "0.1.3"
|
|
6
|
+
|
|
7
|
+
desc "Create gem"
|
|
8
|
+
spec = Gem::Specification.new do |s|
|
|
9
|
+
s.email = 'nullguid@gmail.com'
|
|
10
|
+
s.extensions = 'ext/ipqueue/extconf.rb'
|
|
11
|
+
s.homepage = 'http://ruby-ipqueue.rubyforge.org/'
|
|
12
|
+
s.name = 'ruby-ipqueue'
|
|
13
|
+
s.require_paths << 'ext'
|
|
14
|
+
s.requirements << 'libipq'
|
|
15
|
+
s.rubyforge_project = 'ruby-ipqueue'
|
|
16
|
+
s.summary = 'Rubyish interface to libipq'
|
|
17
|
+
s.description = 'Ruby-ipqueue provides ruby-way object-oriented interface to linux libipq packet mangling library'
|
|
18
|
+
s.version = PKG_VERSION
|
|
19
|
+
s.files = FileList['**/*'].to_a.select{|v| v !~ /pkg|CVS/}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
Rake::GemPackageTask.new(spec) do |p|
|
|
23
|
+
p.gem_spec = spec
|
|
24
|
+
p.need_tar_gz = false
|
|
25
|
+
p.need_zip = false
|
|
26
|
+
end
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
#include <ruby.h>
|
|
2
|
+
#include <libipq/libipq.h>
|
|
3
|
+
#include <linux/netfilter.h>
|
|
4
|
+
|
|
5
|
+
/* FIXME - I don't know how to handle this */
|
|
6
|
+
#define IPQ_MESSAGE_OVERHEAD 256
|
|
7
|
+
|
|
8
|
+
static VALUE cIPQueue, cIPQueuePacket, eTimeout;
|
|
9
|
+
|
|
10
|
+
struct ipqueue_object
|
|
11
|
+
{
|
|
12
|
+
struct ipq_handle *handle;
|
|
13
|
+
size_t range;
|
|
14
|
+
unsigned char *buf;
|
|
15
|
+
size_t len;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
static void fipq_destroy_ipqueue(struct ipqueue_object *ipqueue)
|
|
19
|
+
{
|
|
20
|
+
if(ipq_destroy_handle(ipqueue->handle) == -1)
|
|
21
|
+
rb_raise(rb_eRuntimeError, "%s: %s", ipq_errstr(), strerror(errno));
|
|
22
|
+
xfree(ipqueue->buf);
|
|
23
|
+
xfree(ipqueue);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static VALUE fipq_create_handle(klass, flags, protocol)
|
|
27
|
+
VALUE klass, flags, protocol;
|
|
28
|
+
{
|
|
29
|
+
VALUE obj;
|
|
30
|
+
struct ipq_handle *handle;
|
|
31
|
+
struct ipqueue_object *ipqueue;
|
|
32
|
+
|
|
33
|
+
handle = ipq_create_handle(NUM2INT(flags), NUM2INT(protocol));
|
|
34
|
+
|
|
35
|
+
if(!handle) {
|
|
36
|
+
rb_raise(rb_eRuntimeError, "%s: %s", ipq_errstr(), strerror(errno));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
obj = Data_Make_Struct(klass, struct ipqueue_object, 0, fipq_destroy_ipqueue, ipqueue);
|
|
40
|
+
|
|
41
|
+
/* set default to copy only metainformation */
|
|
42
|
+
ipq_set_mode(handle, IPQ_COPY_META, 0);
|
|
43
|
+
|
|
44
|
+
ipqueue->handle = handle;
|
|
45
|
+
ipqueue->range = 0;
|
|
46
|
+
ipqueue->len = IPQ_MESSAGE_OVERHEAD;
|
|
47
|
+
ipqueue->buf = ALLOC_N(unsigned char, IPQ_MESSAGE_OVERHEAD);
|
|
48
|
+
|
|
49
|
+
return obj;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Assume IPQ_COPY_META when range is zero */
|
|
53
|
+
static VALUE fipq_set_range(obj, range)
|
|
54
|
+
VALUE obj, range;
|
|
55
|
+
{
|
|
56
|
+
struct ipqueue_object *ipqueue;
|
|
57
|
+
|
|
58
|
+
size_t c_range = NUM2INT(range);
|
|
59
|
+
|
|
60
|
+
if(c_range > 65535) {
|
|
61
|
+
rb_raise(rb_eArgError, "invalid range '%d', should be between 0 and 65535", c_range);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
Data_Get_Struct(obj, struct ipqueue_object, ipqueue);
|
|
65
|
+
|
|
66
|
+
if(ipq_set_mode(ipqueue->handle, c_range ? IPQ_COPY_PACKET : IPQ_COPY_META, c_range) < 0)
|
|
67
|
+
rb_raise(rb_eRuntimeError, "%s: %s", ipq_errstr(), strerror(errno));
|
|
68
|
+
|
|
69
|
+
ipqueue->range = c_range;
|
|
70
|
+
|
|
71
|
+
ipqueue->len = c_range + IPQ_MESSAGE_OVERHEAD;
|
|
72
|
+
REALLOC_N(ipqueue->buf, unsigned char, ipqueue->len);
|
|
73
|
+
|
|
74
|
+
return Qnil;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static VALUE fipq_get_range(VALUE obj)
|
|
78
|
+
{
|
|
79
|
+
struct ipqueue_object *ipqueue;
|
|
80
|
+
Data_Get_Struct(obj, struct ipqueue_object, ipqueue);
|
|
81
|
+
|
|
82
|
+
return INT2FIX(ipqueue->range);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static VALUE create_ipqueuepacket(ipq_packet_msg_t *packet_msg, VALUE queue)
|
|
86
|
+
{
|
|
87
|
+
VALUE packet;
|
|
88
|
+
VALUE data[12];
|
|
89
|
+
|
|
90
|
+
/* queue, packet_id, mark, timestamp, hook, indev_name, outdev_name, hw_protocol, hw_type, hw_addr, payload */
|
|
91
|
+
data[0] = queue;
|
|
92
|
+
data[1] = INT2NUM(packet_msg->packet_id);
|
|
93
|
+
data[2] = INT2NUM(packet_msg->mark);
|
|
94
|
+
data[3] = INT2NUM(packet_msg->timestamp_sec);
|
|
95
|
+
data[4] = INT2NUM(packet_msg->timestamp_usec);
|
|
96
|
+
data[5] = INT2FIX(packet_msg->hook);
|
|
97
|
+
data[6] = rb_str_new2(packet_msg->indev_name);
|
|
98
|
+
data[7] = rb_str_new2(packet_msg->outdev_name);
|
|
99
|
+
data[8] = INT2FIX(packet_msg->hw_protocol);
|
|
100
|
+
data[9] = INT2FIX(packet_msg->hw_type);
|
|
101
|
+
data[10] = rb_str_new(packet_msg->hw_addr, packet_msg->hw_addrlen);
|
|
102
|
+
data[11] = rb_str_new(packet_msg->payload, packet_msg->data_len);
|
|
103
|
+
|
|
104
|
+
packet = rb_class_new_instance(12, data, cIPQueuePacket);
|
|
105
|
+
|
|
106
|
+
return packet;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
static VALUE fipq_read(int argc, VALUE *argv, VALUE obj)
|
|
110
|
+
{
|
|
111
|
+
struct ipqueue_object *ipqueue;
|
|
112
|
+
int ret;
|
|
113
|
+
ipq_packet_msg_t *packet_msg;
|
|
114
|
+
|
|
115
|
+
VALUE timeout, payload, packet;
|
|
116
|
+
VALUE error[2];
|
|
117
|
+
|
|
118
|
+
if(rb_scan_args(argc, argv, "01", &timeout) == 0)
|
|
119
|
+
timeout = INT2NUM(0);
|
|
120
|
+
|
|
121
|
+
Data_Get_Struct(obj, struct ipqueue_object, ipqueue);
|
|
122
|
+
|
|
123
|
+
ret = ipq_read(ipqueue->handle, ipqueue->buf, ipqueue->len, NUM2INT(timeout));
|
|
124
|
+
|
|
125
|
+
if(ret < 0)
|
|
126
|
+
rb_raise(rb_eRuntimeError, "%s: %s", ipq_errstr(), strerror(errno));
|
|
127
|
+
if(ret == 0)
|
|
128
|
+
if(errno == EINTR)
|
|
129
|
+
rb_raise(rb_eSignal, "non-blocked signal caught");
|
|
130
|
+
else
|
|
131
|
+
rb_raise(eTimeout, "timeout exceeded");
|
|
132
|
+
|
|
133
|
+
/* dirty hack? */
|
|
134
|
+
if(ipq_message_type(ipqueue->buf) == NLMSG_ERROR) {
|
|
135
|
+
error[0] = rb_str_new2("netlink layer");
|
|
136
|
+
error[1] = INT2FIX(ipq_get_msgerr(ipqueue->buf));
|
|
137
|
+
rb_exc_raise(rb_class_new_instance(2, error, rb_eSystemCallError));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* finally, we've got it */
|
|
141
|
+
packet_msg = ipq_get_packet(ipqueue->buf);
|
|
142
|
+
|
|
143
|
+
return create_ipqueuepacket(packet_msg, obj);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
static VALUE fipq_accept(int argc, VALUE *argv, VALUE obj)
|
|
147
|
+
{
|
|
148
|
+
struct ipqueue_object *ipqueue;
|
|
149
|
+
VALUE packet_id, payload;
|
|
150
|
+
unsigned char *buf = NULL;
|
|
151
|
+
size_t data_len = 0;
|
|
152
|
+
|
|
153
|
+
if(rb_scan_args(argc, argv, "11", &packet_id, &payload) == 2) {
|
|
154
|
+
Check_Type(payload, T_STRING);
|
|
155
|
+
buf = RSTRING(payload)->ptr;
|
|
156
|
+
data_len = RSTRING(payload)->len;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
Data_Get_Struct(obj, struct ipqueue_object, ipqueue);
|
|
160
|
+
|
|
161
|
+
if(ipq_set_verdict(ipqueue->handle, NUM2INT(packet_id), NF_ACCEPT, data_len, buf) < 0)
|
|
162
|
+
rb_raise(rb_eRuntimeError, "%s: %s", ipq_errstr(), strerror(errno));
|
|
163
|
+
|
|
164
|
+
return Qtrue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
static VALUE fipq_drop(obj, packet_id)
|
|
168
|
+
VALUE obj, packet_id;
|
|
169
|
+
{
|
|
170
|
+
struct ipqueue_object *ipqueue;
|
|
171
|
+
|
|
172
|
+
Data_Get_Struct(obj, struct ipqueue_object, ipqueue);
|
|
173
|
+
|
|
174
|
+
if(ipq_set_verdict(ipqueue->handle, NUM2INT(packet_id), NF_DROP, 0, NULL) < 0)
|
|
175
|
+
rb_raise(rb_eRuntimeError, "%s: %s", ipq_errstr(), strerror(errno));
|
|
176
|
+
|
|
177
|
+
return Qtrue;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
void Init_ipqueue()
|
|
181
|
+
{
|
|
182
|
+
cIPQueue = rb_define_class("IPQueue", rb_cObject);
|
|
183
|
+
|
|
184
|
+
/* require our IPQueuePacket class */
|
|
185
|
+
rb_require("ipqueuepacket");
|
|
186
|
+
|
|
187
|
+
cIPQueuePacket = rb_const_get(cIPQueue, rb_intern("Packet"));
|
|
188
|
+
|
|
189
|
+
eTimeout = rb_define_class("Timeout", rb_eException);
|
|
190
|
+
|
|
191
|
+
rb_define_singleton_method(cIPQueue, "new", fipq_create_handle, 2);
|
|
192
|
+
|
|
193
|
+
rb_define_method(cIPQueue, "range=", fipq_set_range, 1);
|
|
194
|
+
rb_define_method(cIPQueue, "range", fipq_get_range, 0);
|
|
195
|
+
rb_define_method(cIPQueue, "read", fipq_read, -1);
|
|
196
|
+
|
|
197
|
+
rb_define_method(cIPQueue, "accept", fipq_accept, -1);
|
|
198
|
+
rb_define_method(cIPQueue, "drop", fipq_drop, 1);
|
|
199
|
+
|
|
200
|
+
#define rb_define_ipq_const(var) \
|
|
201
|
+
rb_define_const(cIPQueue, #var, INT2NUM(var))
|
|
202
|
+
|
|
203
|
+
rb_define_ipq_const(PF_INET);
|
|
204
|
+
rb_define_ipq_const(PF_INET6);
|
|
205
|
+
|
|
206
|
+
rb_define_ipq_const(IPQ_COPY_META);
|
|
207
|
+
rb_define_ipq_const(IPQ_COPY_PACKET);
|
|
208
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class IPQueue::Packet
|
|
2
|
+
attr :packet_id
|
|
3
|
+
attr :mark
|
|
4
|
+
attr :timestamp_sec
|
|
5
|
+
attr :timestamp_usec
|
|
6
|
+
attr :indev_name
|
|
7
|
+
attr :outdev_name
|
|
8
|
+
attr :hw_protocol
|
|
9
|
+
attr :hw_type
|
|
10
|
+
attr :hw_addr
|
|
11
|
+
attr :payload
|
|
12
|
+
|
|
13
|
+
def initialize queue, packet_id, mark, timestamp_sec, timestamp_usec, hook, indev_name, outdev_name, hw_protocol, hw_type, hw_addr, payload
|
|
14
|
+
@queue = queue
|
|
15
|
+
@packet_id = packet_id
|
|
16
|
+
@mark = mark
|
|
17
|
+
@timestamp_sec = timestamp_sec
|
|
18
|
+
@timestamp_usec = timestamp_usec
|
|
19
|
+
@hook = hook
|
|
20
|
+
@indev_name = indev_name
|
|
21
|
+
@outdev_name = outdev_name
|
|
22
|
+
@hw_protocol = hw_protocol
|
|
23
|
+
@hw_type = hw_type
|
|
24
|
+
@hw_addr = hw_addr
|
|
25
|
+
@payload = payload
|
|
26
|
+
end
|
|
27
|
+
def accept(modify = false)
|
|
28
|
+
if modify then @queue.accept(@packet_id, @payload) else @queue.accept(@packet_id) end
|
|
29
|
+
end
|
|
30
|
+
def drop
|
|
31
|
+
@queue.drop(@packet_id)
|
|
32
|
+
end
|
|
33
|
+
def payload
|
|
34
|
+
return @payload
|
|
35
|
+
end
|
|
36
|
+
end
|
data/test/test.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/ruby
|
|
2
|
+
|
|
3
|
+
require 'ipqueue'
|
|
4
|
+
require 'ip-proto'
|
|
5
|
+
|
|
6
|
+
queue = IPQueue.new(0, IPQueue::PF_INET)
|
|
7
|
+
queue.range = 1024
|
|
8
|
+
while true do
|
|
9
|
+
packet = queue.read
|
|
10
|
+
packet.accept true
|
|
11
|
+
ippacket = IP::decode(packet.payload)
|
|
12
|
+
puts ippacket.inspect_detailed
|
|
13
|
+
end
|
data/test/test.sh
ADDED
metadata
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
rubygems_version: 0.9.0
|
|
3
|
+
specification_version: 1
|
|
4
|
+
name: ruby-ipqueue
|
|
5
|
+
version: !ruby/object:Gem::Version
|
|
6
|
+
version: 0.1.3
|
|
7
|
+
date: 2007-01-29 00:00:00 +05:00
|
|
8
|
+
summary: Rubyish interface to libipq
|
|
9
|
+
require_paths:
|
|
10
|
+
- lib
|
|
11
|
+
- ext
|
|
12
|
+
email: nullguid@gmail.com
|
|
13
|
+
homepage: http://ruby-ipqueue.rubyforge.org/
|
|
14
|
+
rubyforge_project: ruby-ipqueue
|
|
15
|
+
description: Ruby-ipqueue provides ruby-way object-oriented interface to linux libipq packet mangling library
|
|
16
|
+
autorequire:
|
|
17
|
+
default_executable:
|
|
18
|
+
bindir: bin
|
|
19
|
+
has_rdoc: false
|
|
20
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
21
|
+
requirements:
|
|
22
|
+
- - ">"
|
|
23
|
+
- !ruby/object:Gem::Version
|
|
24
|
+
version: 0.0.0
|
|
25
|
+
version:
|
|
26
|
+
platform: ruby
|
|
27
|
+
signing_key:
|
|
28
|
+
cert_chain:
|
|
29
|
+
post_install_message:
|
|
30
|
+
authors: []
|
|
31
|
+
|
|
32
|
+
files:
|
|
33
|
+
- ext
|
|
34
|
+
- lib
|
|
35
|
+
- test
|
|
36
|
+
- Rakefile
|
|
37
|
+
- ext/ipqueue
|
|
38
|
+
- ext/ipqueue/extconf.rb
|
|
39
|
+
- ext/ipqueue/ipqueue.c
|
|
40
|
+
- lib/ipqueuepacket.rb
|
|
41
|
+
- test/test.rb
|
|
42
|
+
- test/test.sh
|
|
43
|
+
test_files: []
|
|
44
|
+
|
|
45
|
+
rdoc_options: []
|
|
46
|
+
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
|
|
49
|
+
executables: []
|
|
50
|
+
|
|
51
|
+
extensions:
|
|
52
|
+
- ext/ipqueue/extconf.rb
|
|
53
|
+
requirements:
|
|
54
|
+
- libipq
|
|
55
|
+
dependencies: []
|
|
56
|
+
|