ruby-pcap 0.7.9 → 0.8.0
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/README.md +1 -4
- data/ext/pcap/Pcap.c +125 -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 +13 -9
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
|
+
}
|
data/ext/pcap/tcp_packet.c
CHANGED
@@ -14,10 +14,12 @@
|
|
14
14
|
#define TCP_DATALEN(pkt) (ntohs(IP_HDR(pkt)->ip_len) - \
|
15
15
|
(IP_HDR(pkt)->ip_hl + TCP_HDR(pkt)->th_off) * 4)
|
16
16
|
|
17
|
+
#define TCP_OPTIONS(pkt) ((u_char *) &TCP_HDR(pkt)->th_urp + 2)
|
18
|
+
#define TCP_OPTIONS_LEN(pkt) (((TCP_HDR(pkt)->th_off) * 4) - 20)
|
19
|
+
|
17
20
|
VALUE cTCPPacket;
|
18
21
|
|
19
|
-
#define CheckTruncateTcp(pkt, need)
|
20
|
-
CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated TCP")
|
22
|
+
#define CheckTruncateTcp(pkt, need) CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated TCP")
|
21
23
|
|
22
24
|
VALUE
|
23
25
|
setup_tcp_packet(pkt, tl_len)
|
@@ -64,8 +66,8 @@ TCPP_METHOD(tcpp_win, 16, INT2FIX(ntohs(tcp->th_win)))
|
|
64
66
|
TCPP_METHOD(tcpp_sum, 18, INT2FIX(ntohs(tcp->th_sum)))
|
65
67
|
TCPP_METHOD(tcpp_urp, 20, INT2FIX(ntohs(tcp->th_urp)))
|
66
68
|
|
67
|
-
#define TCPP_FLAG(func, flag)
|
68
|
-
|
69
|
+
#define TCPP_FLAG(func, flag) TCPP_METHOD(func, 14, (tcp->th_flags & flag) ? Qtrue : Qfalse)
|
70
|
+
|
69
71
|
TCPP_FLAG(tcpp_fin, TH_FIN)
|
70
72
|
TCPP_FLAG(tcpp_syn, TH_SYN)
|
71
73
|
TCPP_FLAG(tcpp_rst, TH_RST)
|
@@ -78,7 +80,6 @@ tcpp_data(self)
|
|
78
80
|
VALUE self;
|
79
81
|
{
|
80
82
|
struct packet_object *pkt;
|
81
|
-
VALUE v_len;
|
82
83
|
int len;
|
83
84
|
|
84
85
|
DEBUG_PRINT("tcpp_data");
|
@@ -91,6 +92,308 @@ tcpp_data(self)
|
|
91
92
|
return rb_str_new(TCP_DATA(pkt), len);
|
92
93
|
}
|
93
94
|
|
95
|
+
static VALUE
|
96
|
+
tcpp_options(self)
|
97
|
+
VALUE self;
|
98
|
+
{
|
99
|
+
struct packet_object *pkt;
|
100
|
+
int len;
|
101
|
+
|
102
|
+
DEBUG_PRINT("tcpp_options");
|
103
|
+
GetPacket(self, pkt);
|
104
|
+
len = TCP_OPTIONS_LEN(pkt);
|
105
|
+
if (len < 1 ) return Qnil;
|
106
|
+
return rb_str_new(TCP_OPTIONS(pkt), len);
|
107
|
+
}
|
108
|
+
|
109
|
+
static VALUE
|
110
|
+
tcpp_csumok(self)
|
111
|
+
VALUE self;
|
112
|
+
{
|
113
|
+
struct packet_object *pkt;
|
114
|
+
struct ip *ip;
|
115
|
+
struct tcphdr *tcp;
|
116
|
+
GetPacket(self, pkt);
|
117
|
+
ip = IP_HDR(pkt);
|
118
|
+
tcp = TCP_HDR(pkt);
|
119
|
+
unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
|
120
|
+
unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
|
121
|
+
long sum = 0;
|
122
|
+
unsigned short *temp = (unsigned short *)tcp;
|
123
|
+
int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
|
124
|
+
unsigned short csum = ntohs(tcp->th_sum); // keep the checksum in packet
|
125
|
+
|
126
|
+
// pseudo header sum
|
127
|
+
sum += ntohs(*(ip_src++));
|
128
|
+
sum += ntohs(*ip_src);
|
129
|
+
sum += ntohs(*(ip_dst++));
|
130
|
+
sum += ntohs(*ip_dst);
|
131
|
+
sum += 6;
|
132
|
+
sum += len;
|
133
|
+
// set checksum to zero and sum
|
134
|
+
tcp->th_sum = 0;
|
135
|
+
while(len > 1){
|
136
|
+
sum += ntohs(*temp++);
|
137
|
+
len -= 2;
|
138
|
+
}
|
139
|
+
if(len)
|
140
|
+
sum += ntohs((unsigned short) *((unsigned char *)temp));
|
141
|
+
while(sum>>16)
|
142
|
+
sum = (sum & 0xFFFF) + (sum >> 16);
|
143
|
+
unsigned short answer = ~sum;
|
144
|
+
|
145
|
+
tcp->th_sum = htons(csum); //restore the checkum in packet
|
146
|
+
if (DEBUG_CHECKSUM)
|
147
|
+
printf("TCP csum in packet:%d should be %d\n", csum, answer);
|
148
|
+
if (answer == csum)
|
149
|
+
return Qtrue;
|
150
|
+
return Qfalse;
|
151
|
+
}
|
152
|
+
|
153
|
+
static VALUE
|
154
|
+
tcpp_truncated(self)
|
155
|
+
VALUE self;
|
156
|
+
{
|
157
|
+
struct packet_object *pkt;
|
158
|
+
struct ip *ip;
|
159
|
+
struct tcphdr *tcp;
|
160
|
+
GetPacket(self, pkt);
|
161
|
+
ip = IP_HDR(pkt);
|
162
|
+
tcp = TCP_HDR(pkt);
|
163
|
+
if IsTruncated(pkt, pkt->hdr.layer3_off, ip->ip_hl * 4 + tcp->th_off * 4)
|
164
|
+
return Qtrue;
|
165
|
+
return Qfalse;
|
166
|
+
}
|
167
|
+
|
168
|
+
static VALUE
|
169
|
+
tcpp_data_len(self)
|
170
|
+
VALUE self;
|
171
|
+
{
|
172
|
+
struct packet_object *pkt;
|
173
|
+
GetPacket(self, pkt);
|
174
|
+
|
175
|
+
return INT2FIX(TCP_DATALEN(pkt));
|
176
|
+
}
|
177
|
+
|
178
|
+
/*
|
179
|
+
Calculate TCP checksum and update it in packet
|
180
|
+
*/
|
181
|
+
static VALUE
|
182
|
+
tcpp_csum_update(self)
|
183
|
+
VALUE self;
|
184
|
+
{
|
185
|
+
struct packet_object *pkt;
|
186
|
+
struct ip *ip;
|
187
|
+
struct tcphdr *tcp;
|
188
|
+
GetPacket(self, pkt);
|
189
|
+
ip = IP_HDR(pkt);
|
190
|
+
tcp = TCP_HDR(pkt);
|
191
|
+
unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
|
192
|
+
unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
|
193
|
+
long sum = 0;
|
194
|
+
/* save checksum in packet */
|
195
|
+
unsigned short th_sum = ntohs(tcp->th_sum);
|
196
|
+
unsigned short *temp = (unsigned short *)tcp;
|
197
|
+
int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
|
198
|
+
|
199
|
+
// pseudo header sum
|
200
|
+
sum += ntohs(*(ip_src++));
|
201
|
+
sum += ntohs(*ip_src);
|
202
|
+
sum += ntohs(*(ip_dst++));
|
203
|
+
sum += ntohs(*ip_dst);
|
204
|
+
sum += 6;
|
205
|
+
sum += len;
|
206
|
+
// set checksum to zero and sum
|
207
|
+
tcp->th_sum = 0;
|
208
|
+
while(len > 1){
|
209
|
+
sum += ntohs(*temp++);
|
210
|
+
len -= 2;
|
211
|
+
}
|
212
|
+
if(len)
|
213
|
+
sum += ntohs((unsigned short) *((unsigned char *)temp));
|
214
|
+
while(sum>>16)
|
215
|
+
sum = (sum & 0xFFFF) + (sum >> 16);
|
216
|
+
unsigned short answer = ~sum;
|
217
|
+
/*
|
218
|
+
* set checkum in packet
|
219
|
+
*/
|
220
|
+
tcp->th_sum = htons(answer);
|
221
|
+
/*
|
222
|
+
* no change, return nil
|
223
|
+
*/
|
224
|
+
if (answer == th_sum)
|
225
|
+
return Qnil;
|
226
|
+
/*
|
227
|
+
* return new checkum
|
228
|
+
*/
|
229
|
+
return UINT2NUM(answer);
|
230
|
+
}
|
231
|
+
|
232
|
+
/*
|
233
|
+
* Set TCP source port and update checksum
|
234
|
+
*/
|
235
|
+
static VALUE
|
236
|
+
tcpp_sport_set(self, val)
|
237
|
+
VALUE self, val;
|
238
|
+
{
|
239
|
+
struct packet_object *pkt;
|
240
|
+
struct tcphdr *tcp;
|
241
|
+
GetPacket(self, pkt);
|
242
|
+
tcp = TCP_HDR(pkt);
|
243
|
+
long sum = 0;
|
244
|
+
/*
|
245
|
+
* https://tools.ietf.org/html/rfc1624
|
246
|
+
* HC' = ~(C + (-m) + m')
|
247
|
+
*/
|
248
|
+
sum = ~(~ntohs(tcp->th_sum) - ntohs(tcp->th_sport) + NUM2USHORT(val));
|
249
|
+
while(sum>>16)
|
250
|
+
sum = (sum & 0xFFFF) + (sum >> 16);
|
251
|
+
/*
|
252
|
+
* ttps://tools.ietf.org/html/rfc1624 boundary conditions
|
253
|
+
*/
|
254
|
+
if (sum == 0xFFFF)
|
255
|
+
sum = ~sum;
|
256
|
+
/*
|
257
|
+
* set desired value and new checksum
|
258
|
+
*/
|
259
|
+
tcp->th_sport = htons(NUM2USHORT(val));
|
260
|
+
tcp->th_sum = htons(sum);
|
261
|
+
return val;
|
262
|
+
}
|
263
|
+
|
264
|
+
/*
|
265
|
+
Set TCP destination port and update checksum
|
266
|
+
*/
|
267
|
+
static VALUE
|
268
|
+
tcpp_dport_set(self, val)
|
269
|
+
VALUE self, val;
|
270
|
+
{
|
271
|
+
struct packet_object *pkt;
|
272
|
+
struct tcphdr *tcp;
|
273
|
+
GetPacket(self, pkt);
|
274
|
+
tcp = TCP_HDR(pkt);
|
275
|
+
long sum = 0;
|
276
|
+
/*
|
277
|
+
* https://tools.ietf.org/html/rfc1624
|
278
|
+
* HC' = ~(C + (-m) + m')
|
279
|
+
*/
|
280
|
+
sum = ~(~ntohs(tcp->th_sum) - ntohs(tcp->th_dport) + NUM2USHORT(val));
|
281
|
+
while(sum>>16)
|
282
|
+
sum = (sum & 0xFFFF) + (sum >> 16);
|
283
|
+
/*
|
284
|
+
* ttps://tools.ietf.org/html/rfc1624 boundary conditions
|
285
|
+
*/
|
286
|
+
if (sum == 0xFFFF)
|
287
|
+
sum = ~sum;
|
288
|
+
/*
|
289
|
+
* set desired value and new checksum
|
290
|
+
*/
|
291
|
+
tcp->th_dport = htons(NUM2USHORT(val));
|
292
|
+
tcp->th_sum = htons(sum);
|
293
|
+
return val;
|
294
|
+
}
|
295
|
+
|
296
|
+
/*
|
297
|
+
* IPv6 Specific methods
|
298
|
+
*/
|
299
|
+
|
300
|
+
VALUE cTCPv6Packet;
|
301
|
+
|
302
|
+
#define TCPV6_DATALEN(pkt) (ntohs(IPV6_HDR(pkt)->ip6_plen) - TCP_HDR(pkt)->th_off * 4)
|
303
|
+
|
304
|
+
VALUE
|
305
|
+
setup_tcpv6_packet(pkt, tl_len)
|
306
|
+
struct packet_object *pkt;
|
307
|
+
int tl_len;
|
308
|
+
{
|
309
|
+
VALUE class;
|
310
|
+
|
311
|
+
class = cTCPv6Packet;
|
312
|
+
if (tl_len > 20) {
|
313
|
+
int hl = TCP_HDR(pkt)->th_off * 4;
|
314
|
+
int layer5_len = tl_len - hl;
|
315
|
+
if (layer5_len > 0) {
|
316
|
+
pkt->hdr.layer5_off = pkt->hdr.layer4_off + hl;
|
317
|
+
/* upper layer */
|
318
|
+
}
|
319
|
+
}
|
320
|
+
return class;
|
321
|
+
}
|
322
|
+
|
323
|
+
static VALUE
|
324
|
+
tcppv6_data_len(self)
|
325
|
+
VALUE self;
|
326
|
+
{
|
327
|
+
struct packet_object *pkt;
|
328
|
+
GetPacket(self, pkt);
|
329
|
+
|
330
|
+
return INT2FIX(TCPV6_DATALEN(pkt));
|
331
|
+
}
|
332
|
+
|
333
|
+
static VALUE
|
334
|
+
tcppv6_data(self)
|
335
|
+
VALUE self;
|
336
|
+
{
|
337
|
+
struct packet_object *pkt;
|
338
|
+
int len;
|
339
|
+
|
340
|
+
DEBUG_PRINT("tcppv6_data");
|
341
|
+
GetPacket(self, pkt);
|
342
|
+
|
343
|
+
if (pkt->hdr.layer5_off == OFF_NONEXIST) return Qnil;
|
344
|
+
|
345
|
+
len = MIN(Caplen(pkt, pkt->hdr.layer5_off), TCPV6_DATALEN(pkt));
|
346
|
+
if (len < 1) return Qnil;
|
347
|
+
return rb_str_new(TCP_DATA(pkt), len);
|
348
|
+
}
|
349
|
+
|
350
|
+
static VALUE
|
351
|
+
tcpp_csumokv6(self)
|
352
|
+
VALUE self;
|
353
|
+
{
|
354
|
+
struct packet_object *pkt;
|
355
|
+
struct ip6_hdr *ip;
|
356
|
+
struct tcphdr *tcp;
|
357
|
+
GetPacket(self, pkt);
|
358
|
+
ip = IPV6_HDR(pkt);
|
359
|
+
tcp = TCP_HDR(pkt);
|
360
|
+
unsigned short *ip_src = (void *)&ip->ip6_src.s6_addr;
|
361
|
+
unsigned short *ip_dst = (void *)&ip->ip6_dst.s6_addr;
|
362
|
+
unsigned long sum = 0;
|
363
|
+
unsigned short *temp = (unsigned short *)tcp;
|
364
|
+
int len = ntohs(ip->ip6_plen); // length of ip data
|
365
|
+
unsigned short csum = ntohs(tcp->th_sum); // keep the checksum in packet
|
366
|
+
|
367
|
+
// pseudo header sum
|
368
|
+
int i = 1;
|
369
|
+
for (i = 0; i < 8; i++) {
|
370
|
+
sum += ntohs(*(ip_src));
|
371
|
+
sum += ntohs(*(ip_dst));
|
372
|
+
ip_src++;
|
373
|
+
ip_dst++;
|
374
|
+
}
|
375
|
+
sum += 0x6; /* TCP type */
|
376
|
+
sum += len; /* packet length */
|
377
|
+
// set checksum to zero and sum
|
378
|
+
tcp->th_sum = 0;
|
379
|
+
while(len > 1){
|
380
|
+
sum += ntohs(*temp++);
|
381
|
+
len -= 2;
|
382
|
+
}
|
383
|
+
if(len)
|
384
|
+
sum += ntohs((unsigned short) *((unsigned char *)temp));
|
385
|
+
while(sum>>16)
|
386
|
+
sum = (sum & 0xFFFF) + (sum >> 16);
|
387
|
+
unsigned short answer = ~sum;
|
388
|
+
|
389
|
+
tcp->th_sum = htons(csum); //restore the checkum in packet
|
390
|
+
if (DEBUG_CHECKSUM)
|
391
|
+
printf("TCPv6 csum in packet:%d should be %d\n", csum, answer);
|
392
|
+
if (answer == csum)
|
393
|
+
return Qtrue;
|
394
|
+
return Qfalse;
|
395
|
+
}
|
396
|
+
|
94
397
|
void
|
95
398
|
Init_tcp_packet(void)
|
96
399
|
{
|
@@ -98,11 +401,15 @@ Init_tcp_packet(void)
|
|
98
401
|
|
99
402
|
/* define class TcpPacket */
|
100
403
|
cTCPPacket = rb_define_class_under(mPcap, "TCPPacket", cIPPacket);
|
101
|
-
|
404
|
+
/* define methods under IPv4 */
|
102
405
|
rb_define_method(cTCPPacket, "tcp_sport", tcpp_sport, 0);
|
406
|
+
rb_define_method(cTCPPacket, "tcp_sport=", tcpp_sport_set, 1);
|
103
407
|
rb_define_method(cTCPPacket, "sport", tcpp_sport, 0);
|
408
|
+
rb_define_method(cTCPPacket, "sport=", tcpp_sport_set, 1);
|
104
409
|
rb_define_method(cTCPPacket, "tcp_dport", tcpp_dport, 0);
|
410
|
+
rb_define_method(cTCPPacket, "tcp_dport=", tcpp_dport_set, 1);
|
105
411
|
rb_define_method(cTCPPacket, "dport", tcpp_dport, 0);
|
412
|
+
rb_define_method(cTCPPacket, "dport=", tcpp_dport_set, 1);
|
106
413
|
rb_define_method(cTCPPacket, "tcp_seq", tcpp_seq, 0);
|
107
414
|
rb_define_method(cTCPPacket, "tcp_ack", tcpp_acknum, 0);
|
108
415
|
rb_define_method(cTCPPacket, "tcp_off", tcpp_off, 0);
|
@@ -118,4 +425,37 @@ Init_tcp_packet(void)
|
|
118
425
|
rb_define_method(cTCPPacket, "tcp_ack?", tcpp_ack, 0);
|
119
426
|
rb_define_method(cTCPPacket, "tcp_urg?", tcpp_urg, 0);
|
120
427
|
rb_define_method(cTCPPacket, "tcp_data", tcpp_data, 0);
|
428
|
+
rb_define_method(cTCPPacket, "tcp_data_len", tcpp_data_len, 0);
|
429
|
+
rb_define_method(cTCPPacket, "tcp_options", tcpp_options, 0);
|
430
|
+
rb_define_method(cTCPPacket, "tcp_csum_ok?", tcpp_csumok, 0);
|
431
|
+
rb_define_method(cTCPPacket, "tcp_truncated?", tcpp_truncated, 0);
|
432
|
+
rb_define_method(cTCPPacket, "tcp_csum_update!", tcpp_csum_update, 0);
|
433
|
+
|
434
|
+
// IPv6
|
435
|
+
cTCPv6Packet = rb_define_class_under(mPcap, "TCPv6Packet", cIPv6Packet);
|
436
|
+
/* define methods under IPv6 */
|
437
|
+
rb_define_method(cTCPv6Packet, "tcp_sport", tcpp_sport, 0);
|
438
|
+
rb_define_method(cTCPv6Packet, "sport", tcpp_sport, 0);
|
439
|
+
rb_define_method(cTCPv6Packet, "tcp_dport", tcpp_dport, 0);
|
440
|
+
rb_define_method(cTCPv6Packet, "dport", tcpp_dport, 0);
|
441
|
+
rb_define_method(cTCPv6Packet, "tcp_seq", tcpp_seq, 0);
|
442
|
+
rb_define_method(cTCPv6Packet, "tcp_ack", tcpp_acknum, 0);
|
443
|
+
rb_define_method(cTCPv6Packet, "tcp_off", tcpp_off, 0);
|
444
|
+
rb_define_method(cTCPv6Packet, "tcp_hlen", tcpp_off, 0);
|
445
|
+
rb_define_method(cTCPv6Packet, "tcp_flags", tcpp_flags, 0);
|
446
|
+
rb_define_method(cTCPv6Packet, "tcp_win", tcpp_win, 0);
|
447
|
+
rb_define_method(cTCPv6Packet, "tcp_sum", tcpp_sum, 0);
|
448
|
+
rb_define_method(cTCPv6Packet, "tcp_csumok?", tcpp_csumokv6, 0);
|
449
|
+
rb_define_method(cTCPv6Packet, "tcp_urp", tcpp_urp, 0);
|
450
|
+
rb_define_method(cTCPv6Packet, "tcp_fin?", tcpp_fin, 0);
|
451
|
+
rb_define_method(cTCPv6Packet, "tcp_syn?", tcpp_syn, 0);
|
452
|
+
rb_define_method(cTCPv6Packet, "tcp_rst?", tcpp_rst, 0);
|
453
|
+
rb_define_method(cTCPv6Packet, "tcp_psh?", tcpp_psh, 0);
|
454
|
+
rb_define_method(cTCPv6Packet, "tcp_ack?", tcpp_ack, 0);
|
455
|
+
rb_define_method(cTCPv6Packet, "tcp_urg?", tcpp_urg, 0);
|
456
|
+
rb_define_method(cTCPv6Packet, "tcp_data", tcppv6_data, 0);
|
457
|
+
rb_define_method(cTCPv6Packet, "tcp_data_len", tcppv6_data_len, 0);
|
458
|
+
rb_define_method(cTCPv6Packet, "tcp_options", tcpp_options, 0);
|
459
|
+
|
460
|
+
|
121
461
|
}
|