ruby-pcap 0.7.9 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|