blackfoundry-pcap 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,133 @@
1
+ /*
2
+ * ruby_pcap.h
3
+ *
4
+ * $Id: ruby_pcap.h,v 1.4 2000/08/13 06:56:15 fukusima Exp $
5
+ *
6
+ * Copyright (C) 1998-2000 Masaki Fukushima
7
+ */
8
+
9
+ #ifndef RUBY_PCAP_H
10
+ #define RUBY_PCAP_H
11
+
12
+ #include "ruby.h"
13
+ #include <pcap.h>
14
+ #include <stdio.h>
15
+ #include <netinet/in.h>
16
+ #include <netinet/in_systm.h>
17
+ #include <netinet/ip.h>
18
+ #include <arpa/inet.h>
19
+ #ifndef IP_OFFMASK
20
+ # define IP_OFFMASK 0x1fff
21
+ #endif
22
+ #ifdef linux
23
+ # define __FAVOR_BSD
24
+ #endif
25
+ #include <netinet/tcp.h>
26
+ #include <netinet/udp.h>
27
+ #include <netinet/ip_icmp.h>
28
+ #include <sys/socket.h>
29
+ #include <netdb.h>
30
+
31
+ #ifdef DEBUG
32
+ # define DEBUG_PRINT(x) \
33
+ ((RTEST(ruby_debug) && RTEST(ruby_verbose))?\
34
+ (fprintf(stderr, "%s\n", x),fflush(stderr)) : 0)
35
+ #else
36
+ # define DEBUG_PRINT(x) (0)
37
+ #endif
38
+
39
+ #define UINT32_2_NUM(i) rb_uint2inum(i)
40
+ #ifndef UINT2NUM
41
+ # define UINT2NUM(i) rb_uint2inum(i)
42
+ #endif
43
+ #define MIN(x, y) ((x)<(y) ? (x) : (y))
44
+
45
+
46
+ #define PACKET_MARSHAL_VERSION 1
47
+
48
+ /* ruby config.h defines WORDS_BIGENDIAN if big-endian */
49
+ struct packet_object_header {
50
+ #ifdef WORDS_BIGENDIAN
51
+ u_char version:4; /* marshal format version */
52
+ u_char flags:4; /* flags */
53
+ #else
54
+ u_char flags:4; /* flags */
55
+ u_char version:4; /* marshal format version */
56
+ #endif
57
+ #define POH_UDATA 0x01 /* flag: user data exists */
58
+ #define POH_RSVD1 0x02 /* (reserved) */
59
+ #define POH_RSVD2 0x03 /* (reserved) */
60
+ #define POH_RSVD3 0x04 /* (reserved) */
61
+ u_char dl_type; /* data-link type (DLT_*) */
62
+ u_short layer3_off; /* layer 3 header offset */
63
+ u_short layer4_off; /* layer 4 header offset */
64
+ u_short layer5_off; /* layer 5 header offset */
65
+ #define OFF_NONEXIST 0xffff /* offset value for non-existent layer */
66
+ struct pcap_pkthdr pkthdr; /* pcap packet header */
67
+ };
68
+
69
+ struct packet_object {
70
+ struct packet_object_header hdr; /* packet object header */
71
+ u_char *data; /* packet data */
72
+ VALUE udata; /* user data */
73
+ };
74
+
75
+ #define PKTFLAG_TEST(pkt, flag) ((pkt)->hdr.flags & (flag))
76
+ #define PKTFLAG_SET(pkt, flag, val) \
77
+ ((val) ? ((pkt)->hdr.flags |= (flag)) : ((pkt)->hdr.flags &= ~(flag)))
78
+
79
+ #define LAYER2_HDR(pkt) ((pkt)->data)
80
+ #define LAYER3_HDR(pkt) ((pkt)->data + (pkt)->hdr.layer3_off)
81
+ #define LAYER4_HDR(pkt) ((pkt)->data + (pkt)->hdr.layer4_off)
82
+ #define LAYER5_HDR(pkt) ((pkt)->data + (pkt)->hdr.layer5_off)
83
+
84
+ #define GetPacket(obj, pkt) Data_Get_Struct(obj, struct packet_object, pkt)
85
+ #define Caplen(pkt, from) ((pkt)->hdr.pkthdr.caplen - (from))
86
+ #define CheckTruncate(pkt, from, need, emsg) (\
87
+ (from) + (need) > (pkt)->hdr.pkthdr.caplen ? \
88
+ rb_raise(eTruncatedPacket, (emsg)) : 0 \
89
+ )
90
+
91
+ #define IsKindOf(v, class) RTEST(rb_obj_is_kind_of(v, class))
92
+ #define CheckClass(v, class) ((IsKindOf(v, class)) ? 0 :\
93
+ rb_raise(rb_eTypeError, "wrong type %s (expected %s)",\
94
+ rb_class2name(CLASS_OF(v)), rb_class2name(class)))
95
+
96
+
97
+ /* Pcap.c */
98
+ extern VALUE mPcap, rbpcap_convert;
99
+ extern VALUE ePcapError;
100
+ extern VALUE eTruncatedPacket;
101
+ extern VALUE cFilter;
102
+ void Init_pcap(void);
103
+ VALUE filter_match(VALUE self, VALUE v_pkt);
104
+
105
+ /* packet.c */
106
+ extern VALUE cPacket;
107
+ void Init_packet(void);
108
+ VALUE new_packet(const u_char *, const struct pcap_pkthdr *, int);
109
+
110
+ /* ip_packet.c */
111
+ #define IP_HDR(pkt) ((struct ip *)LAYER3_HDR(pkt))
112
+ #define IP_DATA(pkt) ((u_char *)LAYER4_HDR(pkt))
113
+ extern VALUE cIPPacket;
114
+ void Init_ip_packet(void);
115
+ VALUE setup_ip_packet(struct packet_object *, int);
116
+ VALUE new_ipaddr(struct in_addr *);
117
+
118
+ /* tcp_packet.c */
119
+ extern VALUE cTCPPacket;
120
+ void Init_tcp_packet(void);
121
+ VALUE setup_tcp_packet(struct packet_object *, int);
122
+
123
+ /* udp_packet.c */
124
+ extern VALUE cUDPPacket;
125
+ void Init_udp_packet(void);
126
+ VALUE setup_udp_packet(struct packet_object *, int);
127
+
128
+ /* icmp_packet.c */
129
+ extern VALUE cICMPPacket;
130
+ void Init_icmp_packet(void);
131
+ VALUE setup_icmp_packet(struct packet_object *, int);
132
+
133
+ #endif /* RUBY_PCAP_H */
@@ -0,0 +1,121 @@
1
+ /*
2
+ * tcp_packet.c
3
+ *
4
+ * $Id: tcp_packet.c,v 1.1.1.1 1999/10/27 09:54:38 fukusima Exp $
5
+ *
6
+ * Copyright (C) 1998, 1999 Masaki Fukushima
7
+ */
8
+
9
+ #include "ruby_pcap.h"
10
+ #include <limits.h>
11
+
12
+ #define TCP_HDR(pkt) ((struct tcphdr *)LAYER4_HDR(pkt))
13
+ #define TCP_DATA(pkt) ((u_char *)LAYER5_HDR(pkt))
14
+ #define TCP_DATALEN(pkt) (ntohs(IP_HDR(pkt)->ip_len) - \
15
+ (IP_HDR(pkt)->ip_hl + TCP_HDR(pkt)->th_off) * 4)
16
+
17
+ VALUE cTCPPacket;
18
+
19
+ #define CheckTruncateTcp(pkt, need) \
20
+ CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated TCP")
21
+
22
+ VALUE
23
+ setup_tcp_packet(pkt, tl_len)
24
+ struct packet_object *pkt;
25
+ int tl_len;
26
+ {
27
+ VALUE class;
28
+
29
+ DEBUG_PRINT("setup_tcp_packet");
30
+
31
+ class = cTCPPacket;
32
+ if (tl_len > 20) {
33
+ int hl = TCP_HDR(pkt)->th_off * 4;
34
+ int layer5_len = tl_len - hl;
35
+ if (layer5_len > 0) {
36
+ pkt->hdr.layer5_off = pkt->hdr.layer4_off + hl;
37
+ /* upper layer */
38
+ }
39
+ }
40
+ return class;
41
+ }
42
+
43
+ #define TCPP_METHOD(func, need, val) \
44
+ static VALUE\
45
+ (func)(self)\
46
+ VALUE self;\
47
+ {\
48
+ struct packet_object *pkt;\
49
+ struct tcphdr *tcp;\
50
+ DEBUG_PRINT(#func);\
51
+ GetPacket(self, pkt);\
52
+ CheckTruncateTcp(pkt, (need));\
53
+ tcp = TCP_HDR(pkt);\
54
+ return (val);\
55
+ }
56
+
57
+ TCPP_METHOD(tcpp_sport, 2, INT2FIX(ntohs(tcp->th_sport)))
58
+ TCPP_METHOD(tcpp_dport, 4, INT2FIX(ntohs(tcp->th_dport)))
59
+ TCPP_METHOD(tcpp_seq, 8, UINT32_2_NUM(ntohl(tcp->th_seq)))
60
+ TCPP_METHOD(tcpp_acknum, 12, UINT32_2_NUM(ntohl(tcp->th_ack)))
61
+ TCPP_METHOD(tcpp_off, 13, INT2FIX(tcp->th_off))
62
+ TCPP_METHOD(tcpp_flags, 14, INT2FIX(tcp->th_flags))
63
+ TCPP_METHOD(tcpp_win, 16, INT2FIX(ntohs(tcp->th_win)))
64
+ TCPP_METHOD(tcpp_sum, 18, INT2FIX(ntohs(tcp->th_sum)))
65
+ TCPP_METHOD(tcpp_urp, 20, INT2FIX(ntohs(tcp->th_urp)))
66
+
67
+ #define TCPP_FLAG(func, flag) \
68
+ TCPP_METHOD(func, 14, (tcp->th_flags & flag) ? Qtrue : Qfalse)
69
+ TCPP_FLAG(tcpp_fin, TH_FIN)
70
+ TCPP_FLAG(tcpp_syn, TH_SYN)
71
+ TCPP_FLAG(tcpp_rst, TH_RST)
72
+ TCPP_FLAG(tcpp_psh, TH_PUSH)
73
+ TCPP_FLAG(tcpp_ack, TH_ACK)
74
+ TCPP_FLAG(tcpp_urg, TH_URG)
75
+
76
+ static VALUE
77
+ tcpp_data(self)
78
+ VALUE self;
79
+ {
80
+ struct packet_object *pkt;
81
+ VALUE v_len;
82
+ int len;
83
+
84
+ DEBUG_PRINT("tcpp_data");
85
+ GetPacket(self, pkt);
86
+
87
+ if (pkt->hdr.layer5_off == OFF_NONEXIST) return Qnil;
88
+
89
+ len = MIN(Caplen(pkt, pkt->hdr.layer5_off), TCP_DATALEN(pkt));
90
+ if (len < 1) return Qnil;
91
+ return rb_str_new(TCP_DATA(pkt), len);
92
+ }
93
+
94
+ void
95
+ Init_tcp_packet(void)
96
+ {
97
+ DEBUG_PRINT("Init_tcp_packet");
98
+
99
+ /* define class TcpPacket */
100
+ cTCPPacket = rb_define_class_under(mPcap, "TCPPacket", cIPPacket);
101
+
102
+ rb_define_method(cTCPPacket, "tcp_sport", tcpp_sport, 0);
103
+ rb_define_method(cTCPPacket, "sport", tcpp_sport, 0);
104
+ rb_define_method(cTCPPacket, "tcp_dport", tcpp_dport, 0);
105
+ rb_define_method(cTCPPacket, "dport", tcpp_dport, 0);
106
+ rb_define_method(cTCPPacket, "tcp_seq", tcpp_seq, 0);
107
+ rb_define_method(cTCPPacket, "tcp_ack", tcpp_acknum, 0);
108
+ rb_define_method(cTCPPacket, "tcp_off", tcpp_off, 0);
109
+ rb_define_method(cTCPPacket, "tcp_hlen", tcpp_off, 0);
110
+ rb_define_method(cTCPPacket, "tcp_flags", tcpp_flags, 0);
111
+ rb_define_method(cTCPPacket, "tcp_win", tcpp_win, 0);
112
+ rb_define_method(cTCPPacket, "tcp_sum", tcpp_sum, 0);
113
+ rb_define_method(cTCPPacket, "tcp_urp", tcpp_urp, 0);
114
+ rb_define_method(cTCPPacket, "tcp_fin?", tcpp_fin, 0);
115
+ rb_define_method(cTCPPacket, "tcp_syn?", tcpp_syn, 0);
116
+ rb_define_method(cTCPPacket, "tcp_rst?", tcpp_rst, 0);
117
+ rb_define_method(cTCPPacket, "tcp_psh?", tcpp_psh, 0);
118
+ rb_define_method(cTCPPacket, "tcp_ack?", tcpp_ack, 0);
119
+ rb_define_method(cTCPPacket, "tcp_urg?", tcpp_urg, 0);
120
+ rb_define_method(cTCPPacket, "tcp_data", tcpp_data, 0);
121
+ }
@@ -0,0 +1,96 @@
1
+ /*
2
+ * udp_packet.c
3
+ *
4
+ * $Id: udp_packet.c,v 1.1.1.1 1999/10/27 09:54:38 fukusima Exp $
5
+ *
6
+ * Copyright (C) 1999 Masaki Fukushima
7
+ */
8
+
9
+ #include "ruby_pcap.h"
10
+ #include <limits.h>
11
+
12
+ #define UDP_HDR(pkt) ((struct udphdr *)LAYER4_HDR(pkt))
13
+ #define UDP_DATA(pkt) ((u_char *)LAYER5_HDR(pkt))
14
+ #define UDP_LENGTH(pkt) (ntohs(UDP_HDR(pkt)->uh_ulen))
15
+
16
+ VALUE cUDPPacket;
17
+
18
+ #define CheckTruncateUdp(pkt, need) \
19
+ CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated UDP")
20
+
21
+ VALUE
22
+ setup_udp_packet(pkt, tl_len)
23
+ struct packet_object *pkt;
24
+ int tl_len;
25
+ {
26
+ VALUE class;
27
+
28
+ DEBUG_PRINT("setup_udp_packet");
29
+
30
+ class = cUDPPacket;
31
+ if (tl_len > 8) {
32
+ int hl = 8;
33
+ int layer5_len;
34
+
35
+ tl_len = MIN(tl_len, UDP_LENGTH(pkt));
36
+ layer5_len = tl_len - hl;
37
+ if (layer5_len > 0) {
38
+ pkt->hdr.layer5_off = pkt->hdr.layer4_off + hl;
39
+ /* upper layer */
40
+ }
41
+ }
42
+ return class;
43
+ }
44
+
45
+ #define UDPP_METHOD(func, need, val) \
46
+ static VALUE\
47
+ (func)(self)\
48
+ VALUE self;\
49
+ {\
50
+ struct packet_object *pkt;\
51
+ struct udphdr *udp;\
52
+ DEBUG_PRINT(#func);\
53
+ GetPacket(self, pkt);\
54
+ CheckTruncateUdp(pkt, (need));\
55
+ udp = UDP_HDR(pkt);\
56
+ return (val);\
57
+ }
58
+
59
+ UDPP_METHOD(udpp_sport, 2, INT2FIX(ntohs(udp->uh_sport)))
60
+ UDPP_METHOD(udpp_dport, 4, INT2FIX(ntohs(udp->uh_dport)))
61
+ UDPP_METHOD(udpp_len, 6, INT2FIX(ntohs(udp->uh_ulen)))
62
+ UDPP_METHOD(udpp_sum, 8, INT2FIX(ntohs(udp->uh_sum)))
63
+
64
+ static VALUE
65
+ udpp_data(self)
66
+ VALUE self;
67
+ {
68
+ struct packet_object *pkt;
69
+ int len;
70
+
71
+ DEBUG_PRINT("udpp_data");
72
+ GetPacket(self, pkt);
73
+ CheckTruncateUdp(pkt, 8);
74
+
75
+ if (pkt->hdr.layer5_off == OFF_NONEXIST) return Qnil;
76
+
77
+ len = MIN(Caplen(pkt, pkt->hdr.layer5_off), UDP_LENGTH(pkt)-8);
78
+ return rb_str_new(UDP_DATA(pkt), len);
79
+ }
80
+
81
+ void
82
+ Init_udp_packet(void)
83
+ {
84
+ DEBUG_PRINT("Init_udp_packet");
85
+
86
+ /* define class UdpPacket */
87
+ cUDPPacket = rb_define_class_under(mPcap, "UDPPacket", cIPPacket);
88
+
89
+ rb_define_method(cUDPPacket, "udp_sport", udpp_sport, 0);
90
+ rb_define_method(cUDPPacket, "sport", udpp_sport, 0);
91
+ rb_define_method(cUDPPacket, "udp_dport", udpp_dport, 0);
92
+ rb_define_method(cUDPPacket, "dport", udpp_dport, 0);
93
+ rb_define_method(cUDPPacket, "udp_len", udpp_len, 0);
94
+ rb_define_method(cUDPPacket, "udp_sum", udpp_sum, 0);
95
+ rb_define_method(cUDPPacket, "udp_data", udpp_data, 0);
96
+ }
@@ -0,0 +1,116 @@
1
+
2
+ module Pcap
3
+ class Packet
4
+ def to_s
5
+ 'Some packet'
6
+ end
7
+
8
+ def inspect
9
+ "#<#{self.class}: #{self}>"
10
+ end
11
+ end
12
+
13
+ class IPPacket
14
+ def to_s
15
+ "#{ip_src} > #{ip_dst}"
16
+ end
17
+ end
18
+
19
+ class TCPPacket
20
+ def tcp_data_len
21
+ ip_len - 4 * (ip_hlen + tcp_hlen)
22
+ end
23
+
24
+ def tcp_flags_s
25
+ return \
26
+ (tcp_urg? ? 'U' : '.') +
27
+ (tcp_ack? ? 'A' : '.') +
28
+ (tcp_psh? ? 'P' : '.') +
29
+ (tcp_rst? ? 'R' : '.') +
30
+ (tcp_syn? ? 'S' : '.') +
31
+ (tcp_fin? ? 'F' : '.')
32
+ end
33
+
34
+ def to_s
35
+ "#{src}:#{sport} > #{dst}:#{dport} #{tcp_flags_s}"
36
+ end
37
+ end
38
+
39
+ class UDPPacket
40
+ def to_s
41
+ "#{src}:#{sport} > #{dst}:#{dport} len #{udp_len} sum #{udp_sum}"
42
+ end
43
+ end
44
+
45
+ class ICMPPacket
46
+ def to_s
47
+ "#{src} > #{dst}: icmp: #{icmp_typestr}"
48
+ end
49
+ end
50
+
51
+ #
52
+ # Backword compatibility
53
+ #
54
+ IpPacket = IPPacket
55
+ IpAddress = IPAddress
56
+ TcpPacket = TCPPacket
57
+ UdpPacket = UDPPacket
58
+
59
+ # IpAddress is now obsolete.
60
+ # New class IPAddress is implemented in C.
61
+ =begin
62
+ class IpAddress
63
+ def initialize(a)
64
+ raise AurgumentError unless a.is_a?(Integer)
65
+ @addr = a
66
+ end
67
+
68
+ def to_i
69
+ return @addr
70
+ end
71
+
72
+ def ==(other)
73
+ @addr == other.to_i
74
+ end
75
+
76
+ alias === ==
77
+ alias eql? ==
78
+
79
+ def to_num_s
80
+ return ((@addr >> 24) & 0xff).to_s + "." +
81
+ ((@addr >> 16) & 0xff).to_s + "." +
82
+ ((@addr >> 8) & 0xff).to_s + "." +
83
+ (@addr & 0xff).to_s;
84
+ end
85
+
86
+ def hostname
87
+ addr = self.to_num_s
88
+ # "require 'socket'" is here because of the order of
89
+ # ext initialization in static linked binary
90
+ require 'socket'
91
+ begin
92
+ return Socket.gethostbyname(addr)[0]
93
+ rescue SocketError
94
+ return addr
95
+ end
96
+ end
97
+
98
+ def to_s
99
+ if Pcap.convert?
100
+ return hostname
101
+ else
102
+ return to_num_s
103
+ end
104
+ end
105
+ end
106
+ =end
107
+ end
108
+
109
+ class Time
110
+ # tcpdump style format
111
+ def tcpdump
112
+ sprintf "%0.2d:%0.2d:%0.2d.%0.6d", hour, min, sec, tv_usec
113
+ end
114
+ end
115
+
116
+ autoload :Pcaplet, 'pcaplet'