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.
@@ -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: []