1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
18 from ryu.lib import addrconv
19 from . import ether_types as ether
20 from . import packet_base
22 ARP_HW_TYPE_ETHERNET = 1 # ethernet hardware type
31 class arp(packet_base.PacketBase):
32 """ARP (RFC 826) header encoder/decoder class.
34 An instance has the following attributes at least.
35 Most of them are same to the on-wire counterparts but in host byte order.
36 IPv4 addresses are represented as a string like '192.0.2.1'.
37 MAC addresses are represented as a string like '08:60:6e:7f:74:e7'.
38 __init__ takes the corresponding args in this order.
40 ============== ===================================== =====================
41 Attribute Description Example
42 ============== ===================================== =====================
43 hwtype Hardware address.
44 proto Protocol address.
45 hlen byte length of each hardware address.
46 plen byte length of each protocol address.
47 opcode operation codes.
48 src_mac Hardware address of sender. '08:60:6e:7f:74:e7'
49 src_ip Protocol address of sender. '192.0.2.1'
50 dst_mac Hardware address of target. '00:00:00:00:00:00'
51 dst_ip Protocol address of target. '192.0.2.2'
52 ============== ===================================== =====================
55 _PACK_STR = '!HHBBH6s4s6s4s'
56 _MIN_LEN = struct.calcsize(_PACK_STR)
59 'src_mac', 'src_ip', 'dst_mac', 'dst_ip'
63 def __init__(self, hwtype=ARP_HW_TYPE_ETHERNET, proto=ether.ETH_TYPE_IP,
64 hlen=6, plen=4, opcode=ARP_REQUEST,
65 src_mac='ff:ff:ff:ff:ff:ff',
67 dst_mac='ff:ff:ff:ff:ff:ff',
69 super(arp, self).__init__()
75 self.src_mac = src_mac
77 self.dst_mac = dst_mac
82 (hwtype, proto, hlen, plen, opcode, src_mac, src_ip,
83 dst_mac, dst_ip) = struct.unpack_from(cls._PACK_STR, buf)
84 return cls(hwtype, proto, hlen, plen, opcode,
85 addrconv.mac.bin_to_text(src_mac),
86 addrconv.ipv4.bin_to_text(src_ip),
87 addrconv.mac.bin_to_text(dst_mac),
88 addrconv.ipv4.bin_to_text(dst_ip)), None, buf[arp._MIN_LEN:]
90 def serialize(self, payload, prev):
91 return struct.pack(arp._PACK_STR, self.hwtype, self.proto,
92 self.hlen, self.plen, self.opcode,
93 addrconv.mac.text_to_bin(self.src_mac),
94 addrconv.ipv4.text_to_bin(self.src_ip),
95 addrconv.mac.text_to_bin(self.dst_mac),
96 addrconv.ipv4.text_to_bin(self.dst_ip))
99 def arp_ip(opcode, src_mac, src_ip, dst_mac, dst_ip):
100 """A convenient wrapper for IPv4 ARP for Ethernet.
102 This is an equivalent of the following code.
104 arp(ARP_HW_TYPE_ETHERNET, ether.ETH_TYPE_IP, \
105 6, 4, opcode, src_mac, src_ip, dst_mac, dst_ip)
107 return arp(ARP_HW_TYPE_ETHERNET, ether.ETH_TYPE_IP,
108 6, # ether mac address length
109 4, # ipv4 address length,
110 opcode, src_mac, src_ip, dst_mac, dst_ip)