1
1
require "./ethernet"
2
2
require "./utils"
3
+ require "socket"
4
+
5
+ ARPHRD_ETHER = 1
6
+ ARPOP_REQUEST = 1
7
+ ETH_ALEN = 6
8
+ ETH_P_ARP = [ 0x0806 ] . pack ( "S>" ) . unpack1 ( "S" )
9
+ ETH_P_IP = 0x0800
10
+ ETH_TYPE_NUMBER_ARP = 0x0806
11
+ PACKET_BROADCAST = 1
12
+ PACKET_HOST = 0
13
+ TIMEOUT_TIME = 3
14
+ AF_PACKET = 0x11
15
+ ETH_P_ALL = [ 0x0003 ] . pack ( 'S>' ) . unpack ( 'S' ) . first
16
+ SIOCGIFINDEX = 0x8933 # bits/ioctls.h
17
+ SIOCGIFHWADDR = 0x8927 # linux/sockios.h
3
18
4
19
class Arp
20
+ # TODO: attr_readerいらないかも
21
+ include Utils
5
22
attr_reader :hardware_type , :protocol_type , :hardware_size , :protocol_size , :opcode , :sender_mac_addr ,
6
23
:sender_ip_addr , :target_mac_addr , :target_ip_addr
7
- def initialize ( sender_mac_addr , sender_ip_addr , target_ip_addr )
8
- @hardware_type = 0x0001
9
- @protocol_type = 0x0800
10
- @hardware_size = 0x06
11
- @protocol_size = 0x04
12
- @opcode = 0x0001
13
- @sender_mac_addr = sender_mac_addr
14
- @sender_ip_addr = sender_ip_addr
15
- @target_mac_addr = 0x000000000000
16
- @target_ip_addr = target_ip_addr
24
+ def initialize ( target_ip_addr )
25
+ @hardware_type = [ 0x0001 ] . pack ( "S>" )
26
+ @protocol_type = [ 0x0800 ] . pack ( "S>" )
27
+ @hardware_size = [ 0x06 ] . pack ( "C" )
28
+ @protocol_size = [ 0x04 ] . pack ( "C" )
29
+ @opcode = [ 0x0001 ] . pack ( "S>" )
30
+ @sender_mac_addr = get_packed_local_mac_addr
31
+ @sender_ip_addr = get_packed_local_ip_addr
32
+ @target_mac_addr = [ 0 ] . pack ( "C" ) * 6
33
+ @target_ip_addr = target_ip_addr . split ( "." ) . map ( &:to_i ) . pack ( "C*" )
34
+ end
35
+
36
+ def sum_data_without_address
37
+ @hardware_type + @protocol_type + @hardware_size + @protocol_size + @opcode
38
+ end
39
+
40
+ def sum_address
41
+ sum_data_without_address + @sender_mac_addr + @sender_ip_addr + @target_mac_addr + @target_ip_addr
42
+ end
43
+
44
+ def bind_if ( socket , interface )
45
+ # Get the system's internal interface index value
46
+ ifreq = [ interface , '' ] . pack ( 'a16a16' )
47
+ socket . ioctl ( SIOCGIFINDEX , ifreq )
48
+ index_str = ifreq [ 16 , 4 ]
49
+
50
+ # Build our sockaddr_ll struct so we can bind to this interface. The struct
51
+ # is defined in linux/if_packet.h and requires the interface index.
52
+ eth_p_all_hbo = [ ETH_P_ALL ] . pack ( 'S' ) . unpack ( 'S>' ) . first
53
+ sll = [ Socket ::AF_PACKET , eth_p_all_hbo , index_str ] . pack ( 'SS>a16' )
54
+ socket . bind ( sll )
17
55
end
18
56
19
57
def send
20
- utils = Utils . new
21
- Ethernet . new ( "ARP" , utils . get_local_mac_and_ip_addr . mac_addr , "ff:ff:ff:ff:ff:ff" )
58
+ type = [ 0x0806 ] . pack ( "S>" )
59
+ src_mac_addr = get_packed_local_mac_addr
60
+ dst_mac_addr = [ 255 ] . pack ( "C" ) * 6
61
+ header = Ethernet . new ( type , src_mac_addr , dst_mac_addr ) . header
62
+ data = sum_data_without_address + sum_address
63
+ request = header + data
64
+ s = Socket . new ( AF_PACKET , Socket ::SOCK_RAW , ETH_P_ALL )
65
+ # ARPはUDP通信でもTCP通信でもない?
66
+ # client_socket_addr = Socket.pack_sockaddr_in(8863, Socket.gethostname)
67
+ # s.bind(client_socket_addr)
68
+ # bind_if(s)
69
+ bind_if ( s , "en0" )
70
+ res = s . send ( request , 0 )
71
+ p res
22
72
end
23
73
end
24
74
25
- a = Arp . new ( 1 , 1 , 1 )
26
- p a
75
+ Arp . new ( "10.14.69.254" ) . send
0 commit comments