ruby-pcap 0.7.9 → 0.8.1
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.
- checksums.yaml +5 -5
- data/.github/workflows/build.yml +26 -0
- data/README.md +3 -7
- data/examples/capture_duration.rb +28 -0
- data/ext/pcap/Pcap.c +152 -23
- data/ext/pcap/arp_packet.c +82 -0
- data/ext/pcap/icmp_packet.c +35 -0
- data/ext/pcap/icmpv6_packet.c +107 -0
- data/ext/pcap/ip_packet.c +16 -7
- data/ext/pcap/ipv6_packet.c +162 -0
- data/ext/pcap/packet.c +36 -8
- data/ext/pcap/ruby_pcap.h +34 -4
- data/ext/pcap/slow_protocol_packet.c +29 -0
- data/ext/pcap/tcp_packet.c +346 -6
- data/ext/pcap/udp_packet.c +262 -1
- data/lib/pcap/packet.rb +123 -11
- data/ruby-pcap.gemspec +4 -4
- metadata +16 -10
- data/.travis.yml +0 -13
@@ -0,0 +1,162 @@
|
|
1
|
+
/*
|
2
|
+
* ipv6_packet.c
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "ruby_pcap.h"
|
6
|
+
|
7
|
+
VALUE cIPv6Packet;
|
8
|
+
|
9
|
+
#define CheckTruncateIpv6(pkt, need) CheckTruncate(pkt, pkt->hdr.layer3_off, need, "truncated IPv6")
|
10
|
+
#define IPV6_HL 40
|
11
|
+
|
12
|
+
VALUE
|
13
|
+
setup_ipv6_packet(pkt, nl_len)
|
14
|
+
struct packet_object *pkt;
|
15
|
+
int nl_len;
|
16
|
+
{
|
17
|
+
VALUE class;
|
18
|
+
|
19
|
+
class = cIPv6Packet;
|
20
|
+
pkt->hdr.layer4_off = pkt->hdr.layer3_off + IPV6_HL;
|
21
|
+
switch (IPV6_HDR(pkt)->ip6_nxt) {
|
22
|
+
case IPPROTO_TCP:
|
23
|
+
DEBUG_PRINT("setup_tcpv6_packet");
|
24
|
+
class = setup_tcpv6_packet(pkt, nl_len - IPV6_HL);
|
25
|
+
break;
|
26
|
+
case IPPROTO_UDP:
|
27
|
+
DEBUG_PRINT("setup_udpv6_packet");
|
28
|
+
class = setup_udpv6_packet(pkt, nl_len - IPV6_HL);
|
29
|
+
break;
|
30
|
+
case IPPROTO_ICMPV6:
|
31
|
+
DEBUG_PRINT("setup_icmpv6_packet");
|
32
|
+
class = setup_icmpv6_packet(pkt);
|
33
|
+
break;
|
34
|
+
}
|
35
|
+
return class;
|
36
|
+
}
|
37
|
+
|
38
|
+
#define IPV6P_METHOD(func, val) \
|
39
|
+
static VALUE\
|
40
|
+
(func)(self)\
|
41
|
+
VALUE self;\
|
42
|
+
{\
|
43
|
+
struct ip6_hdr *ip;\
|
44
|
+
\
|
45
|
+
DEBUG_PRINT(#func);\
|
46
|
+
ip = IPV6_HDR_OBJ(self);\
|
47
|
+
return (val);\
|
48
|
+
}
|
49
|
+
|
50
|
+
IPV6P_METHOD(ipp_ver, INT2FIX(ip->ip6_vfc >> 4))
|
51
|
+
/*
|
52
|
+
The bits of this field hold two values.
|
53
|
+
The six most-significant bits hold the Differentiated Services (DS) field, which is used to classify packets.
|
54
|
+
Currently, all standard DS fields end with a '0' bit. Any DS field that ends with two '1' bits is intended for local or experimental use.[4]
|
55
|
+
The remaining two bits are used for Explicit Congestion Notification (ECN);
|
56
|
+
priority values subdivide into ranges: traffic where the source provides congestion control and non-congestion control traffic.
|
57
|
+
*/
|
58
|
+
IPV6P_METHOD(ipp_tc, INT2FIX((ntohl(ip->ip6_flow) & 0x0FF00000) >> 20))
|
59
|
+
IPV6P_METHOD(ipp_ds, INT2FIX((ntohl(ip->ip6_flow) & 0x0FF00000) >> 22))
|
60
|
+
IPV6P_METHOD(ipp_ecn, INT2FIX((ntohl(ip->ip6_flow) & 0x00300000) >> 20))
|
61
|
+
IPV6P_METHOD(ipp_fl, INT2FIX(ntohl(ip->ip6_flow) & 0x000FFFFF))
|
62
|
+
IPV6P_METHOD(ipp_pl, INT2FIX(ntohs(ip->ip6_plen)))
|
63
|
+
IPV6P_METHOD(ipp_nh, INT2FIX(ip->ip6_nxt))
|
64
|
+
IPV6P_METHOD(ipp_hl, INT2FIX(ip->ip6_hlim))
|
65
|
+
|
66
|
+
|
67
|
+
static VALUE
|
68
|
+
ipp_truncated(self)
|
69
|
+
VALUE self;
|
70
|
+
{
|
71
|
+
struct packet_object *pkt;
|
72
|
+
struct ip6_hdr *ip;
|
73
|
+
GetPacket(self, pkt);
|
74
|
+
ip = IPV6_HDR(pkt);
|
75
|
+
if IsTruncated(pkt, pkt->hdr.layer3_off, ntohs(ip->ip6_plen))
|
76
|
+
return Qtrue;
|
77
|
+
return Qfalse;
|
78
|
+
}
|
79
|
+
|
80
|
+
static VALUE
|
81
|
+
ipp_data(self)
|
82
|
+
VALUE self;
|
83
|
+
{
|
84
|
+
struct packet_object *pkt;
|
85
|
+
struct ip6_hdr *ip;
|
86
|
+
int len;
|
87
|
+
|
88
|
+
GetPacket(self, pkt);
|
89
|
+
ip = IPV6_HDR(pkt);
|
90
|
+
CheckTruncateIpv6(pkt, 20);
|
91
|
+
len = pkt->hdr.pkthdr.caplen - pkt->hdr.layer3_off - IPV6_HL;
|
92
|
+
return rb_str_new((u_char *)ip + IPV6_HL, len);
|
93
|
+
}
|
94
|
+
|
95
|
+
/*
|
96
|
+
* IPv6Address
|
97
|
+
*/
|
98
|
+
|
99
|
+
static VALUE
|
100
|
+
ipp_src_i(self)
|
101
|
+
VALUE self;
|
102
|
+
{
|
103
|
+
struct ip6_hdr *ip;
|
104
|
+
ip = (struct ip6_hdr *)IPV6_HDR_OBJ(self);
|
105
|
+
return rb_integer_unpack(ip->ip6_src.s6_addr, 16, 1, 0, INTEGER_PACK_BIG_ENDIAN);
|
106
|
+
}
|
107
|
+
|
108
|
+
static VALUE
|
109
|
+
ipp_src_s(self)
|
110
|
+
VALUE self;
|
111
|
+
{
|
112
|
+
struct ip6_hdr *ip;
|
113
|
+
char buff[INET6_ADDRSTRLEN];
|
114
|
+
ip = (struct ip6_hdr *)IPV6_HDR_OBJ(self);
|
115
|
+
|
116
|
+
inet_ntop(AF_INET6, ip->ip6_src.s6_addr, buff, INET6_ADDRSTRLEN);
|
117
|
+
return rb_str_new2(buff);
|
118
|
+
}
|
119
|
+
|
120
|
+
static VALUE
|
121
|
+
ipp_dst_i(self)
|
122
|
+
VALUE self;
|
123
|
+
{
|
124
|
+
struct ip6_hdr *ip;
|
125
|
+
ip = IPV6_HDR_OBJ(self);
|
126
|
+
return rb_integer_unpack(ip->ip6_dst.s6_addr, 16, 1, 0, INTEGER_PACK_BIG_ENDIAN);
|
127
|
+
}
|
128
|
+
|
129
|
+
static VALUE
|
130
|
+
ipp_dst_s(self)
|
131
|
+
VALUE self;
|
132
|
+
{
|
133
|
+
char buff[INET6_ADDRSTRLEN];
|
134
|
+
struct ip6_hdr *ip;
|
135
|
+
ip = IPV6_HDR_OBJ(self);
|
136
|
+
|
137
|
+
inet_ntop(AF_INET6, ip->ip6_dst.s6_addr, buff, INET6_ADDRSTRLEN);
|
138
|
+
return rb_str_new2(buff);
|
139
|
+
}
|
140
|
+
|
141
|
+
void
|
142
|
+
Init_ipv6_packet(void)
|
143
|
+
{
|
144
|
+
DEBUG_PRINT("Init_ipv6_packet");
|
145
|
+
|
146
|
+
cIPv6Packet = rb_define_class_under(mPcap, "IPv6Packet", cPacket);
|
147
|
+
|
148
|
+
rb_define_method(cIPv6Packet, "ip_ver", ipp_ver, 0);
|
149
|
+
rb_define_method(cIPv6Packet, "ip_tc", ipp_tc, 0);
|
150
|
+
rb_define_method(cIPv6Packet, "ip_ds", ipp_ds, 0);
|
151
|
+
rb_define_method(cIPv6Packet, "ip_ecn", ipp_ecn, 0);
|
152
|
+
rb_define_method(cIPv6Packet, "ip_fl", ipp_fl, 0); /* IPv6 flow label */
|
153
|
+
rb_define_method(cIPv6Packet, "ip_pl", ipp_pl, 0); /* IPv6 Payload length */
|
154
|
+
rb_define_method(cIPv6Packet, "ip_nh", ipp_nh, 0); /* IPv6 Next header */
|
155
|
+
rb_define_method(cIPv6Packet, "ip_hl", ipp_hl, 0); /* IPv6 Hop limit */
|
156
|
+
rb_define_method(cIPv6Packet, "src_s", ipp_src_s, 0);
|
157
|
+
rb_define_method(cIPv6Packet, "dst_s", ipp_dst_s, 0);
|
158
|
+
rb_define_method(cIPv6Packet, "src_i", ipp_src_i, 0);
|
159
|
+
rb_define_method(cIPv6Packet, "dst_i", ipp_dst_i, 0);
|
160
|
+
rb_define_method(cIPv6Packet, "ip_data", ipp_data, 0);
|
161
|
+
rb_define_method(cIPv6Packet, "ip_truncated?", ipp_truncated, 0);
|
162
|
+
}
|
data/ext/pcap/packet.c
CHANGED
@@ -11,7 +11,17 @@
|
|
11
11
|
#include <sys/socket.h>
|
12
12
|
#include <net/if.h>
|
13
13
|
#include <netinet/if_ether.h>
|
14
|
+
#ifndef ETH_P_IPV6
|
15
|
+
#define ETH_P_IPV6 0x86DD /* IPv6 packet */
|
16
|
+
#endif
|
17
|
+
|
18
|
+
#ifndef ETH_P_SLOW
|
19
|
+
#define ETH_P_SLOW 0x8809 /* Slow Protocol frame */
|
20
|
+
#endif
|
14
21
|
|
22
|
+
#ifndef ETH_P_ARP
|
23
|
+
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
|
24
|
+
#endif
|
15
25
|
#define DL_HDR(pkt) ((u_char *)LAYER2_HDR(pkt))
|
16
26
|
#define DL_DATA(pkt) ((u_char *)LAYER3_HDR(pkt))
|
17
27
|
|
@@ -125,14 +135,18 @@ new_packet(data, pkthdr, dl_type)
|
|
125
135
|
case ETHERTYPE_IP:
|
126
136
|
class = setup_ip_packet(pkt, nl_len);
|
127
137
|
break;
|
138
|
+
case ETH_P_IPV6:
|
139
|
+
class = setup_ipv6_packet(pkt, nl_len);
|
140
|
+
break;
|
141
|
+
case ETH_P_ARP:
|
142
|
+
class = setup_arp_packet(pkt, nl_len);
|
143
|
+
break;
|
144
|
+
case ETH_P_SLOW:
|
145
|
+
class = setup_slow_protocol_packet(pkt, nl_len);
|
146
|
+
break;
|
128
147
|
}
|
129
148
|
}
|
130
|
-
|
131
|
-
if (ruby_debug && TYPE(class) != T_CLASS) {
|
132
|
-
rb_fatal("not class");
|
133
|
-
}
|
134
|
-
#endif
|
135
|
-
return Data_Wrap_Struct(class, mark_packet, free_packet, pkt);
|
149
|
+
return Data_Wrap_Struct(class, mark_packet, free_packet, pkt);
|
136
150
|
}
|
137
151
|
|
138
152
|
static VALUE
|
@@ -282,14 +296,18 @@ static VALUE\
|
|
282
296
|
PACKET_METHOD(packet_get_udata, pkt->udata);
|
283
297
|
PACKET_METHOD(packet_datalink, INT2FIX(pkt->hdr.dl_type));
|
284
298
|
PACKET_METHOD(packet_ip, rb_obj_is_kind_of(self, cIPPacket));
|
285
|
-
PACKET_METHOD(
|
286
|
-
PACKET_METHOD(
|
299
|
+
PACKET_METHOD(packet_ipv6, rb_obj_is_kind_of(self, cIPv6Packet));
|
300
|
+
PACKET_METHOD(packet_tcp, rb_obj_is_kind_of(self, cTCPPacket) | rb_obj_is_kind_of(self, cTCPv6Packet));
|
301
|
+
PACKET_METHOD(packet_udp, rb_obj_is_kind_of(self, cUDPPacket) | rb_obj_is_kind_of(self, cUDPv6Packet));
|
287
302
|
PACKET_METHOD(packet_length, UINT32_2_NUM(pkt->hdr.pkthdr.len));
|
288
303
|
PACKET_METHOD(packet_caplen, UINT32_2_NUM(pkt->hdr.pkthdr.caplen));
|
289
304
|
PACKET_METHOD(packet_time, rb_time_new(pkt->hdr.pkthdr.ts.tv_sec,
|
290
305
|
pkt->hdr.pkthdr.ts.tv_usec));
|
291
306
|
PACKET_METHOD(packet_time_i, rb_int2inum(pkt->hdr.pkthdr.ts.tv_sec));
|
292
307
|
PACKET_METHOD(packet_raw_data, rb_str_new(pkt->data, pkt->hdr.pkthdr.caplen));
|
308
|
+
PACKET_METHOD(packet_arp, rb_obj_is_kind_of(self, cARPPacket));
|
309
|
+
PACKET_METHOD(packet_lacp, rb_obj_is_kind_of(self, cLACPPacket));
|
310
|
+
|
293
311
|
|
294
312
|
void
|
295
313
|
Init_packet(void)
|
@@ -308,9 +326,12 @@ Init_packet(void)
|
|
308
326
|
rb_define_method(cPacket, "udata", packet_get_udata, 0);
|
309
327
|
rb_define_method(cPacket, "udata=", packet_set_udata, 1);
|
310
328
|
rb_define_method(cPacket, "datalink", packet_datalink, 0);
|
329
|
+
rb_define_method(cPacket, "arp?", packet_arp, 0);
|
311
330
|
rb_define_method(cPacket, "ip?", packet_ip, 0);
|
331
|
+
rb_define_method(cPacket, "ipv6?", packet_ipv6, 0);
|
312
332
|
rb_define_method(cPacket, "tcp?", packet_tcp, 0);
|
313
333
|
rb_define_method(cPacket, "udp?", packet_udp, 0);
|
334
|
+
rb_define_method(cPacket, "lacp?", packet_lacp, 0);
|
314
335
|
rb_define_method(cPacket, "length", packet_length, 0);
|
315
336
|
rb_define_method(cPacket, "size", packet_length, 0);
|
316
337
|
rb_define_method(cPacket, "caplen", packet_caplen, 0);
|
@@ -325,4 +346,11 @@ Init_packet(void)
|
|
325
346
|
id_load = rb_intern("load");
|
326
347
|
id_dump = rb_intern("dump");
|
327
348
|
Init_ip_packet();
|
349
|
+
Init_arp_packet();
|
350
|
+
Init_ipv6_packet();
|
351
|
+
Init_tcp_packet();
|
352
|
+
Init_udp_packet();
|
353
|
+
Init_icmp_packet();
|
354
|
+
Init_icmpv6_packet();
|
355
|
+
Init_sp_packet();
|
328
356
|
}
|
data/ext/pcap/ruby_pcap.h
CHANGED
@@ -15,6 +15,8 @@
|
|
15
15
|
#include <netinet/in.h>
|
16
16
|
#include <netinet/in_systm.h>
|
17
17
|
#include <netinet/ip.h>
|
18
|
+
#include <netinet/ip6.h>
|
19
|
+
#include <netinet/icmp6.h>
|
18
20
|
#include <arpa/inet.h>
|
19
21
|
#ifndef IP_OFFMASK
|
20
22
|
# define IP_OFFMASK 0x1fff
|
@@ -29,10 +31,7 @@
|
|
29
31
|
#include <netdb.h>
|
30
32
|
|
31
33
|
#ifdef DEBUG
|
32
|
-
# define DEBUG_PRINT(x)
|
33
|
-
((RTEST(ruby_debug) && RTEST(ruby_verbose))?\
|
34
|
-
(fprintf(stderr, "%s\n", x),fflush(stderr)) : 0)\
|
35
|
-
} while (0)
|
34
|
+
# define DEBUG_PRINT(x) fprintf(stderr, "%s\n", x),fflush(stderr)
|
36
35
|
#else
|
37
36
|
# define DEBUG_PRINT(x) do {} while (0)
|
38
37
|
#endif
|
@@ -89,11 +88,16 @@ struct packet_object {
|
|
89
88
|
rb_raise(eTruncatedPacket, (emsg)) : 0 \
|
90
89
|
)
|
91
90
|
|
91
|
+
#define IsTruncated(pkt, from, need) (\
|
92
|
+
(from) + (need) > (pkt)->hdr.pkthdr.caplen ? \
|
93
|
+
1 : 0 \
|
94
|
+
)
|
92
95
|
#define IsKindOf(v, class) RTEST(rb_obj_is_kind_of(v, class))
|
93
96
|
#define CheckClass(v, class) ((IsKindOf(v, class)) ? 0 :\
|
94
97
|
rb_raise(rb_eTypeError, "wrong type %s (expected %s)",\
|
95
98
|
rb_class2name(CLASS_OF(v)), rb_class2name(class)))
|
96
99
|
|
100
|
+
#define DEBUG_CHECKSUM 0
|
97
101
|
|
98
102
|
/* Pcap.c */
|
99
103
|
extern VALUE mPcap, rbpcap_convert;
|
@@ -118,17 +122,43 @@ VALUE new_ipaddr(struct in_addr *);
|
|
118
122
|
|
119
123
|
/* tcp_packet.c */
|
120
124
|
extern VALUE cTCPPacket;
|
125
|
+
extern VALUE cTCPv6Packet;
|
121
126
|
void Init_tcp_packet(void);
|
122
127
|
VALUE setup_tcp_packet(struct packet_object *, int);
|
128
|
+
VALUE setup_tcpv6_packet(struct packet_object *, int);
|
129
|
+
|
130
|
+
/* ipv6_packet.c */
|
131
|
+
#define IPV6_HDR(pkt) ((struct ip6_hdr *)LAYER3_HDR(pkt))
|
132
|
+
#define IPV6_HDR_OBJ(self) ((struct ip6_hdr *)LAYER3_HDR((struct packet_object *)DATA_PTR(self)))
|
133
|
+
extern VALUE cIPv6Packet;
|
134
|
+
void Init_ipv6_packet(void);
|
135
|
+
VALUE setup_ipv6_packet(struct packet_object *, int);
|
123
136
|
|
124
137
|
/* udp_packet.c */
|
125
138
|
extern VALUE cUDPPacket;
|
139
|
+
extern VALUE cUDPv6Packet;
|
126
140
|
void Init_udp_packet(void);
|
127
141
|
VALUE setup_udp_packet(struct packet_object *, int);
|
142
|
+
VALUE setup_udpv6_packet(struct packet_object *, int);
|
128
143
|
|
129
144
|
/* icmp_packet.c */
|
130
145
|
extern VALUE cICMPPacket;
|
146
|
+
extern VALUE cICMPv6Packet;
|
131
147
|
void Init_icmp_packet(void);
|
148
|
+
void Init_icmpv6_packet(void);
|
132
149
|
VALUE setup_icmp_packet(struct packet_object *, int);
|
150
|
+
VALUE setup_icmpv6_packet(struct packet_object *);
|
133
151
|
|
152
|
+
|
153
|
+
/* arp_packet.c */
|
154
|
+
extern VALUE cARPPacket;
|
155
|
+
void Init_arp_packet(void);
|
156
|
+
VALUE setup_arp_packet(struct packet_object *, int);
|
157
|
+
|
158
|
+
/* slow_protocol_packet.c */
|
159
|
+
extern VALUE cSPPacket;
|
160
|
+
extern VALUE cLACPPacket;
|
161
|
+
void Init_sp_packet(void);
|
162
|
+
VALUE setup_slow_protocol_packet(struct packet_object *, int);
|
134
163
|
#endif /* RUBY_PCAP_H */
|
164
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#include "ruby_pcap.h"
|
2
|
+
|
3
|
+
VALUE cSPPacket;
|
4
|
+
VALUE cLACPPacket;
|
5
|
+
|
6
|
+
VALUE
|
7
|
+
setup_slow_protocol_packet(pkt, nl_len)
|
8
|
+
struct packet_object *pkt;
|
9
|
+
int nl_len;
|
10
|
+
{
|
11
|
+
VALUE class;
|
12
|
+
|
13
|
+
DEBUG_PRINT("setup_slow_protocol_packet");
|
14
|
+
if (pkt->data[14] == 0x01) {
|
15
|
+
class = cLACPPacket;
|
16
|
+
} else {
|
17
|
+
class = cSPPacket;
|
18
|
+
}
|
19
|
+
return class;
|
20
|
+
}
|
21
|
+
|
22
|
+
void
|
23
|
+
Init_sp_packet(void)
|
24
|
+
{
|
25
|
+
DEBUG_PRINT("Init_sp_packet");
|
26
|
+
|
27
|
+
cSPPacket = rb_define_class_under(mPcap, "SPPacket", cPacket);
|
28
|
+
cLACPPacket = rb_define_class_under(mPcap, "LACPPacket", cSPPacket);
|
29
|
+
}
|