ruby-pcap 0.7.9 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -78,6 +78,250 @@ udpp_data(self)
78
78
  return rb_str_new(UDP_DATA(pkt), len);
79
79
  }
80
80
 
81
+ static VALUE
82
+ udpp_csum_update(self)
83
+ VALUE self;
84
+ {
85
+ struct packet_object *pkt;
86
+ struct ip *ip;
87
+ struct udphdr *udp;
88
+ GetPacket(self, pkt);
89
+ ip = IP_HDR(pkt);
90
+ udp = UDP_HDR(pkt);
91
+ unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
92
+ unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
93
+ long sum = 0;
94
+ /* save checksum in packet */
95
+ unsigned short uh_sum = ntohs(udp->uh_sum);
96
+ unsigned short answer = 0;
97
+ unsigned short *temp = (unsigned short *)udp;
98
+ int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
99
+
100
+ // pseudo header sum
101
+ sum += ntohs(*(ip_src++));
102
+ sum += ntohs(*ip_src);
103
+ sum += ntohs(*(ip_dst++));
104
+ sum += ntohs(*ip_dst);
105
+ sum += 17;
106
+ sum += len;
107
+ // set checksum to zero and sum
108
+ udp->uh_sum = 0;
109
+ while (len > 1){
110
+ sum += ntohs(*temp++);
111
+ len -= 2;
112
+ }
113
+ if (len)
114
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
115
+ while(sum>>16)
116
+ sum = (sum & 0xFFFF) + (sum >> 16);
117
+
118
+ answer = ~sum;
119
+ if (answer == 0)
120
+ answer = ~answer;
121
+ /*
122
+ * set checkum in packet
123
+ */
124
+ udp->uh_sum = htons(answer);
125
+ /*
126
+ * no change, return nil
127
+ */
128
+ if (answer == uh_sum)
129
+ return Qnil;
130
+ /*
131
+ * return new checkum
132
+ */
133
+ return UINT2NUM(answer);
134
+ }
135
+
136
+ /*
137
+ Set UDP source port and update checksum
138
+ */
139
+ static VALUE
140
+ udpp_sport_set(self, val)
141
+ VALUE self, val;
142
+ {
143
+ struct packet_object *pkt;
144
+ struct udphdr *udp;
145
+ long sum = 0;
146
+ GetPacket(self, pkt);
147
+ udp = UDP_HDR(pkt);
148
+ /*
149
+ * https://tools.ietf.org/html/rfc1624
150
+ * HC' = ~(C + (-m) + m')
151
+ */
152
+ sum = ~(~ntohs(udp->uh_sum) - ntohs(udp->uh_sport) + NUM2USHORT(val));
153
+ while(sum>>16)
154
+ sum = (sum & 0xFFFF) + (sum >> 16);
155
+ /*
156
+ * set desired value and new checksum
157
+ */
158
+ udp->uh_sport = htons(NUM2USHORT(val));
159
+ udp->uh_sum = htons(sum);
160
+ return val;
161
+ }
162
+ /*
163
+ Set UDP destination port and update checksum
164
+ */
165
+ static VALUE
166
+ udpp_dport_set(self, val)
167
+ VALUE self, val;
168
+ {
169
+ struct packet_object *pkt;
170
+ struct udphdr *udp;
171
+ long sum = 0;
172
+ GetPacket(self, pkt);
173
+ udp = UDP_HDR(pkt);
174
+ /*
175
+ * https://tools.ietf.org/html/rfc1624
176
+ * HC' = ~(C + (-m) + m')
177
+ */
178
+ sum = ~(~ntohs(udp->uh_sum) - ntohs(udp->uh_dport) + NUM2USHORT(val));
179
+ while(sum>>16)
180
+ sum = (sum & 0xFFFF) + (sum >> 16);
181
+ /*
182
+ * set desired value and new checksum
183
+ */
184
+ udp->uh_dport = htons(NUM2USHORT(val));
185
+ udp->uh_sum = htons(sum);
186
+ return val;
187
+ }
188
+ /*
189
+ * IPv6 Specific methods
190
+ */
191
+ VALUE cUDPv6Packet;
192
+
193
+ VALUE
194
+ setup_udpv6_packet(pkt, tl_len)
195
+ struct packet_object *pkt;
196
+ int tl_len;
197
+ {
198
+ VALUE class;
199
+ DEBUG_PRINT("setup_udpv6_packet");
200
+ class = cUDPv6Packet;
201
+ if (tl_len > 8) {
202
+ int hl = 8;
203
+ int layer5_len;
204
+
205
+ tl_len = MIN(tl_len, UDP_LENGTH(pkt));
206
+ layer5_len = tl_len - hl;
207
+ if (layer5_len > 0) {
208
+ pkt->hdr.layer5_off = pkt->hdr.layer4_off + hl;
209
+ /* upper layer */
210
+ }
211
+ }
212
+ return class;
213
+ }
214
+
215
+ static VALUE
216
+ udpp_csumokv6(self)
217
+ VALUE self;
218
+ {
219
+ struct packet_object *pkt;
220
+ struct ip6_hdr *ip;
221
+ struct udphdr *udp;
222
+ GetPacket(self, pkt);
223
+ ip = IPV6_HDR(pkt);
224
+ udp = UDP_HDR(pkt);
225
+ unsigned short *ip_src = (void *)&ip->ip6_src.s6_addr;
226
+ unsigned short *ip_dst = (void *)&ip->ip6_dst.s6_addr;
227
+ long sum = 0;
228
+ unsigned short answer = 0;
229
+ unsigned short *temp = (unsigned short *)udp;
230
+ int len = ntohs(ip->ip6_plen); // length of ip data
231
+ unsigned short csum = ntohs(udp->uh_sum); // keep the checksum in packet
232
+
233
+ // pseudo header sum
234
+ int i = 1;
235
+ for (i = 0; i < 8; i++) {
236
+ sum += ntohs(*(ip_src));
237
+ sum += ntohs(*(ip_dst));
238
+ ip_src++;
239
+ ip_dst++;
240
+ }
241
+ sum += 0x11; // UDP
242
+ sum += len;
243
+ // set checksum to zero and sum
244
+ udp->uh_sum = 0;
245
+ while (len > 1){
246
+ sum += ntohs(*temp++);
247
+ len -= 2;
248
+ }
249
+ if (len)
250
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
251
+ while(sum>>16)
252
+ sum = (sum & 0xFFFF) + (sum >> 16);
253
+ answer = ~sum;
254
+ if (answer == 0)
255
+ answer = ~answer;
256
+ udp->uh_sum = htons(csum); //restore the checkum in packet
257
+ if (DEBUG_CHECKSUM)
258
+ printf("UDP csum in packet:%d should be %d\n", csum, answer);
259
+ if (answer == csum)
260
+ return Qtrue;
261
+ return Qfalse;
262
+ }
263
+
264
+ static VALUE
265
+ udpp_csumok(self)
266
+ VALUE self;
267
+ {
268
+ struct packet_object *pkt;
269
+ struct ip *ip;
270
+ struct udphdr *udp;
271
+ GetPacket(self, pkt);
272
+ ip = IP_HDR(pkt);
273
+ udp = UDP_HDR(pkt);
274
+ unsigned short *ip_src = (void *)&ip->ip_src.s_addr;
275
+ unsigned short *ip_dst = (void *)&ip->ip_dst.s_addr;
276
+ long sum = 0;
277
+ unsigned short answer = 0;
278
+ unsigned short *temp = (unsigned short *)udp;
279
+ int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data
280
+ int csum = ntohs(udp->uh_sum); // keep the checksum in packet
281
+
282
+ // pseudo header sum
283
+ sum += ntohs(*(ip_src++));
284
+ sum += ntohs(*ip_src);
285
+ sum += ntohs(*(ip_dst++));
286
+ sum += ntohs(*ip_dst);
287
+ sum += 17;
288
+ sum += len;
289
+ // set checksum to zero and sum
290
+ udp->uh_sum = 0;
291
+ while (len > 1){
292
+ sum += ntohs(*temp++);
293
+ len -= 2;
294
+ }
295
+ if (len)
296
+ sum += ntohs((unsigned short) *((unsigned char *)temp));
297
+ while(sum>>16)
298
+ sum = (sum & 0xFFFF) + (sum >> 16);
299
+
300
+ answer = ~sum;
301
+ if (answer == 0)
302
+ answer = ~answer;
303
+ udp->uh_sum = csum; //restore the checkum in packet
304
+ if (DEBUG_CHECKSUM)
305
+ printf("UDP csum in packet:%d should be %d\n", csum, answer);
306
+ if (answer == csum)
307
+ return Qtrue;
308
+ return Qfalse;
309
+ }
310
+ static VALUE
311
+ udpp_truncated(self)
312
+ VALUE self;
313
+ {
314
+ struct packet_object *pkt;
315
+ struct ip *ip;
316
+ struct udphdr *udp;
317
+ GetPacket(self, pkt);
318
+ ip = IP_HDR(pkt);
319
+ udp = UDP_HDR(pkt);
320
+ if IsTruncated(pkt, pkt->hdr.layer3_off, ip->ip_hl * 4 + ntohs(udp->uh_ulen))
321
+ return Qtrue;
322
+ return Qfalse;
323
+ }
324
+
81
325
  void
82
326
  Init_udp_packet(void)
83
327
  {
@@ -85,12 +329,29 @@ Init_udp_packet(void)
85
329
 
86
330
  /* define class UdpPacket */
87
331
  cUDPPacket = rb_define_class_under(mPcap, "UDPPacket", cIPPacket);
88
-
332
+ cUDPv6Packet = rb_define_class_under(mPcap, "UDPv6Packet", cIPv6Packet);
333
+ /* define methods under IPv4 */
89
334
  rb_define_method(cUDPPacket, "udp_sport", udpp_sport, 0);
335
+ rb_define_method(cUDPPacket, "udp_sport=", udpp_sport_set, 1);
90
336
  rb_define_method(cUDPPacket, "sport", udpp_sport, 0);
337
+ rb_define_method(cUDPPacket, "sport=", udpp_sport_set, 1);
91
338
  rb_define_method(cUDPPacket, "udp_dport", udpp_dport, 0);
339
+ rb_define_method(cUDPPacket, "udp_dport=", udpp_dport_set, 1);
92
340
  rb_define_method(cUDPPacket, "dport", udpp_dport, 0);
341
+ rb_define_method(cUDPPacket, "dport=", udpp_dport_set, 1);
93
342
  rb_define_method(cUDPPacket, "udp_len", udpp_len, 0);
94
343
  rb_define_method(cUDPPacket, "udp_sum", udpp_sum, 0);
95
344
  rb_define_method(cUDPPacket, "udp_data", udpp_data, 0);
345
+ rb_define_method(cUDPPacket, "udp_csum_ok?", udpp_csumok, 0);
346
+ rb_define_method(cUDPPacket, "udp_truncated?", udpp_truncated, 0);
347
+ rb_define_method(cUDPPacket, "udp_csum_update!", udpp_csum_update, 0);
348
+ /* define methods under IPv6 */
349
+ rb_define_method(cUDPv6Packet, "udp_sport", udpp_sport, 0);
350
+ rb_define_method(cUDPv6Packet, "sport", udpp_sport, 0);
351
+ rb_define_method(cUDPv6Packet, "udp_dport", udpp_dport, 0);
352
+ rb_define_method(cUDPv6Packet, "dport", udpp_dport, 0);
353
+ rb_define_method(cUDPv6Packet, "udp_len", udpp_len, 0);
354
+ rb_define_method(cUDPv6Packet, "udp_sum", udpp_sum, 0);
355
+ rb_define_method(cUDPv6Packet, "udp_data", udpp_data, 0);
356
+ rb_define_method(cUDPv6Packet, "udp_csum_ok?", udpp_csumokv6, 0);
96
357
  }
data/lib/pcap/packet.rb CHANGED
@@ -7,6 +7,21 @@ module Pcap
7
7
  def inspect
8
8
  "#<#{self.class}: #{self}>"
9
9
  end
10
+ def src_mac_address
11
+ return unpack_hex_string(raw_data[6, 12])
12
+ end
13
+
14
+ def dst_mac_address
15
+ return unpack_hex_string(raw_data[0, 6])
16
+ end
17
+
18
+ def ethertype
19
+ raw_data[12, 14].unpack('n')[0]
20
+ end
21
+
22
+ def unpack_hex_string(hex)
23
+ hex.unpack('H2H2H2H2H2H2').join('')
24
+ end
10
25
  end
11
26
 
12
27
  class IPPacket
@@ -15,6 +30,12 @@ module Pcap
15
30
  end
16
31
  end
17
32
 
33
+ class IPv6Packet
34
+ def to_s
35
+ "#{src_s} > #{dst_s} next header #{ip_nh}"
36
+ end
37
+ end
38
+
18
39
  class TCPPacket
19
40
  def tcp_data_len
20
41
  ip_len - 4 * (ip_hlen + tcp_hlen)
@@ -33,32 +54,123 @@ module Pcap
33
54
  def to_s
34
55
  "#{src}:#{sport} > #{dst}:#{dport} #{tcp_flags_s}"
35
56
  end
57
+ end
36
58
 
37
- def src_mac_address
38
- return unpack_hex_string(raw_data[6, 12])
59
+ class UDPPacket
60
+ def to_s
61
+ "#{src}:#{sport} > #{dst}:#{dport} len #{udp_len} sum #{udp_sum}"
39
62
  end
63
+ end
40
64
 
41
- def dst_mac_address
42
- return unpack_hex_string(raw_data[0, 6])
65
+ class ICMPPacket
66
+ def to_s
67
+ "#{src} > #{dst}: icmp: #{icmp_typestr}"
43
68
  end
69
+ end
44
70
 
45
- def unpack_hex_string(hex)
46
- return hex.unpack('H2H2H2H2H2H2').join('')
71
+ class TCPv6Packet
72
+
73
+ def tcp_flags_s
74
+ return \
75
+ (tcp_urg? ? 'U' : '.') +
76
+ (tcp_ack? ? 'A' : '.') +
77
+ (tcp_psh? ? 'P' : '.') +
78
+ (tcp_rst? ? 'R' : '.') +
79
+ (tcp_syn? ? 'S' : '.') +
80
+ (tcp_fin? ? 'F' : '.')
47
81
  end
48
- end
49
82
 
50
- class UDPPacket
51
83
  def to_s
52
- "#{src}:#{sport} > #{dst}:#{dport} len #{udp_len} sum #{udp_sum}"
84
+ "#{src_s}:#{sport} > #{dst_s}:#{dport} #{tcp_flags_s}"
53
85
  end
54
86
  end
55
87
 
56
- class ICMPPacket
88
+ class UDPv6Packet
57
89
  def to_s
58
- "#{src} > #{dst}: icmp: #{icmp_typestr}"
90
+ "#{src_s}:#{sport} > #{dst_s}:#{dport} len #{udp_len} sum #{udp_sum}"
91
+ end
92
+ end
93
+
94
+ # Slow protocol frames
95
+ class SPPacket
96
+
97
+ # return Slow protocol subtype: 0x01 LACP, 0x02 Marker 0x03 EFM OAM
98
+ def sp_subtype
99
+ raw_data[14].unpack('C')[0]
59
100
  end
60
101
  end
61
102
 
103
+ # LACP frames
104
+ class LACPPacket
105
+
106
+ LACP_ACTIVITY = 0x01
107
+ LACP_TIMEOUT = 0x02
108
+ LACP_AGGR = 0x04
109
+ LACP_SYNC = 0x08
110
+ LACP_COLLECTING = 0x10
111
+ LACP_DISTR = 0x20
112
+ LACP_DEFAULTED = 0x40
113
+ LACP_EXPIRED = 0x80
114
+
115
+ # return LACP Version
116
+ def version
117
+ raw_data[15].unpack('C')[0]
118
+ end
119
+
120
+ # return Actor LACP flags in human readable form
121
+ def actor_flags
122
+ parse_flags(actor_info['Actor State'])
123
+ end
124
+
125
+ # return Actor LACP flags in human readable form
126
+ def partner_flags
127
+ parse_flags(partner_info['Partner State'])
128
+ end
129
+
130
+ # return LACP Actor TLV
131
+ def actor_info
132
+ # throw error if 1st TLV is not Actor
133
+ raise 'error in actor TLV' if raw_data[16].unpack('C')[0] != 1
134
+ {
135
+ 'Actor System Priority' => raw_data[18,19].unpack('n')[0],
136
+ 'Actor System Id' => unpack_hex_string(raw_data[20, 26]),
137
+ 'Actor Key' => raw_data[26,27].unpack('n')[0],
138
+ 'Actor Port Priority' => raw_data[28,29].unpack('n')[0],
139
+ 'Actor Port' => raw_data[30,31].unpack('n')[0],
140
+ 'Actor State' => raw_data[32].unpack('C')[0].to_i
141
+ }
142
+ end
143
+ # return LACP Partner TLV
144
+ def partner_info
145
+ # throw error if 2nd TLV is not Partner
146
+ actor_tlv_len = raw_data[17].unpack('C')[0]
147
+ base = 16 + actor_tlv_len
148
+ raise 'error in partner TLV' if raw_data[base].unpack('C')[0] != 2
149
+ base += 2
150
+ {
151
+ 'Partner System Priority' => raw_data[base, base + 1].unpack('n')[0],
152
+ 'Partner System Id' => unpack_hex_string(raw_data[base + 2, base + 7]),
153
+ 'Partner Key' => raw_data[base + 8,base + 9].unpack('n')[0],
154
+ 'Partner Port Priority' => raw_data[base + 10,base + 11].unpack('n')[0],
155
+ 'Partner Port' => raw_data[base + 12,base + 13].unpack('n')[0],
156
+ 'Partner State' => raw_data[base + 14].unpack('C')[0].to_i
157
+ }
158
+ end
159
+
160
+ # parse LACP flags based on 802.3ad-2000
161
+ def parse_flags(flags)
162
+ {
163
+ 'Activity' => (LACP_ACTIVITY & flags).zero? ? 'Passive' : 'Active',
164
+ 'Timeout' => (LACP_TIMEOUT & flags).zero? ? 'Long' : 'Short',
165
+ 'Aggregation' => (LACP_AGGR & flags).zero? ? 'Individual' : 'Aggregatable',
166
+ 'Synchronization' => (LACP_SYNC & flags).zero? ? 'OutSync' : 'InSync',
167
+ 'Collecting' => (LACP_COLLECTING & flags).zero? ? 'NotCollecting' : 'Collecting',
168
+ 'Distributing' => (LACP_DISTR & flags).zero? ? 'NotDistributing' : 'Distributing',
169
+ 'Defaulted' => (LACP_DEFAULTED & flags).zero? ? 'RecvPartner' : 'DefaultPartner',
170
+ 'Expired' => (LACP_EXPIRED & flags).zero? ? 'NotExpired' : 'Expired'
171
+ }
172
+ end
173
+ end
62
174
  #
63
175
  # Backword compatibility
64
176
  #
data/ruby-pcap.gemspec CHANGED
@@ -4,12 +4,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = "ruby-pcap"
7
- gem.version = "0.7.9"
8
- gem.authors = [%q{Masaki Fukushima}, %q{Andrew Hobson}]
9
- gem.email = ["mbarczak@gmail.com"]
7
+ gem.version = "0.8.0"
8
+ gem.authors = [%q{Masaki Fukushima}, %q{Andrew Hobson}, %q{Marcus Barczak}]
9
+ gem.email = ["opensource@vitosha-labs.bg"]
10
10
  gem.description = %q{Ruby interface to LBL Packet Capture library. This library also includes classes to access packet header fields.}
11
11
  gem.summary = %q{Ruby interface to LBL Packet Capture library.}
12
- gem.homepage = "https://github.com/ickymettle/ruby-pcap"
12
+ gem.homepage = "https://github.com/vitoshalabs/ruby-pcap"
13
13
  gem.license = "GPL-2.0"
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
metadata CHANGED
@@ -1,15 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-pcap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.9
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Fukushima
8
8
  - Andrew Hobson
9
- autorequire:
9
+ - Marcus Barczak
10
+ autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2015-07-20 00:00:00.000000000 Z
13
+ date: 2022-01-30 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: rake-compiler
@@ -28,7 +29,7 @@ dependencies:
28
29
  description: Ruby interface to LBL Packet Capture library. This library also includes
29
30
  classes to access packet header fields.
30
31
  email:
31
- - mbarczak@gmail.com
32
+ - opensource@vitosha-labs.bg
32
33
  executables: []
33
34
  extensions:
34
35
  - ext/pcap/extconf.rb
@@ -75,11 +76,15 @@ files:
75
76
  - examples/tcpdump.rb
76
77
  - examples/test.rb
77
78
  - ext/pcap/Pcap.c
79
+ - ext/pcap/arp_packet.c
78
80
  - ext/pcap/extconf.rb
79
81
  - ext/pcap/icmp_packet.c
82
+ - ext/pcap/icmpv6_packet.c
80
83
  - ext/pcap/ip_packet.c
84
+ - ext/pcap/ipv6_packet.c
81
85
  - ext/pcap/packet.c
82
86
  - ext/pcap/ruby_pcap.h
87
+ - ext/pcap/slow_protocol_packet.c
83
88
  - ext/pcap/tcp_packet.c
84
89
  - ext/pcap/udp_packet.c
85
90
  - lib/pcap/packet.rb
@@ -87,11 +92,11 @@ files:
87
92
  - lib/pcap/tcpdump_time_format.rb
88
93
  - lib/pcap_misc.rb
89
94
  - ruby-pcap.gemspec
90
- homepage: https://github.com/ickymettle/ruby-pcap
95
+ homepage: https://github.com/vitoshalabs/ruby-pcap
91
96
  licenses:
92
97
  - GPL-2.0
93
98
  metadata: {}
94
- post_install_message:
99
+ post_install_message:
95
100
  rdoc_options: []
96
101
  require_paths:
97
102
  - lib
@@ -106,9 +111,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
111
  - !ruby/object:Gem::Version
107
112
  version: '0'
108
113
  requirements: []
109
- rubyforge_project:
110
- rubygems_version: 2.2.3
111
- signing_key:
114
+ rubygems_version: 3.1.6
115
+ signing_key:
112
116
  specification_version: 4
113
117
  summary: Ruby interface to LBL Packet Capture library.
114
118
  test_files: []