rfc826 An Ethernet Address Resolution Protocol (ARP)
リンクは以下から
Abstract The implementation of protocol P on a sending host S decides, through protocol P's routing mechanism, that it wants to transmit to a target host T located some place on a connected piece of 10Mbit Ethernet cable. To actually transmit the Ethernet packet a 48.bit Ethernet address must be generated. The addresses of hosts within protocol P are not always compatible with the corresponding Ethernet address (being different lengths or values). Presented here is a protocol that allows dynamic distribution of the information needed to build tables to translate an address A in protocol P's address space into a 48.bit Ethernet address.
The Problem: ------------ The world is a jungle in general, and the networking game contributes many animals. At nearly every layer of a network architecture there are several potential protocols that could be used. For example, at a high level, there is TELNET and SUPDUP for remote login. Somewhere below that there is a reliable byte stream protocol, which might be CHAOS protocol, DOD TCP, Xerox BSP or DECnet. Even closer to the hardware is the logical transport layer, which might be CHAOS, DOD Internet, Xerox PUP, or DECnet. The 10Mbit Ethernet allows all of these protocols (and more) to coexist on a single cable by means of a type field in the Ethernet packet header. However, the 10Mbit Ethernet requires 48.bit addresses on the physical cable, yet most protocol addresses are not 48.bits long, nor do they necessarily have any relationship to the 48.bit Ethernet address of the hardware. For example, CHAOS addresses are 16.bits, DOD Internet addresses are 32.bits, and Xerox PUP addresses are 8.bits. A protocol is needed to dynamically distribute the correspondences between a <protocol, address> pair and a 48.bit Ethernet address.
上位層のプロトコルの多くがイーサネットを使用しています。 しかし、10Mbit Ethernetは物理ケーブル上に48.bitのアドレスを必要としますが、ほとんどのプロトコルアドレスは48.bit長ではなく、またハードウェアの48.bit Ethernetアドレスと必ずしも関係があるわけでもない。 TCP/IP を使用するためにはIPアドレスを使うが、MACアドレスとIPアドレスのアドレス解決をできる必要がある。
Packet format: -------------- To communicate mappings from <protocol, address> pairs to 48.bit Ethernet addresses, a packet format that embodies the Address Resolution protocol is needed. The format of the packet follows. Ethernet transmission layer (not necessarily accessible to the user): 48.bit: Ethernet address of destination 48.bit: Ethernet address of sender 16.bit: Protocol type = ether_type$ADDRESS_RESOLUTION Ethernet packet data: 16.bit: (ar$hrd) Hardware address space (e.g., Ethernet, Packet Radio Net.) 16.bit: (ar$pro) Protocol address space. For Ethernet hardware, this is from the set of type fields ether_typ$<protocol>. 8.bit: (ar$hln) byte length of each hardware address 8.bit: (ar$pln) byte length of each protocol address 16.bit: (ar$op) opcode (ares_op$REQUEST | ares_op$REPLY) nbytes: (ar$sha) Hardware address of sender of this packet, n from the ar$hln field. mbytes: (ar$spa) Protocol address of sender of this packet, m from the ar$pln field. nbytes: (ar$tha) Hardware address of target of this packet (if known). mbytes: (ar$tpa) Protocol address of target.
まず、Ethernet headerの情報がある。
Ethernet transmission layer (not necessarily accessible to the user): 48.bit: Ethernet address of destination 48.bit: Ethernet address of sender 16.bit: Protocol type = ether_type$ADDRESS_RESOLUTION
16.bit: Protocol type はこの場合ARPを示す0x0806
を使用する。
Ethertype Ethertype Description Reference (decimal) (hex) 2054 0806 Address Resolution Protocol [RFC7042]
from: https://www.iana.org/assignments/ieee-802-numbers/ieee-802-numbers.txt
他のEthertypesとしてIETFが定めたものとして以下のものがある
B.1. Some Ethertypes Specified by the IETF 0x0800 Internet Protocol Version 4 (IPv4) 0x0806 Address Resolution Protocol (ARP) 0x0808 Frame Relay ARP 0x22F3 TRILL 0x22F4 L2-IS-IS 0x8035 Reverse Address Resolution Protocol (RARP) 0x86DD Internet Protocol Version 6 (IPv6) 0x880B Point-to-Point Protocol (PPP) 0x880C General Switch Management Protocol (GSMP) 0x8847 MPLS 0x8848 MPLS with upstream-assigned label 0x8861 Multicast Channel Allocation Protocol (MCAP) 0x8863 PPP over Ethernet (PPPoE) Discovery Stage 0x8864 PPP over Ethernet (PPPoE) Session Stage 0x893B TRILL Fine Grained Labeling (FGL) 0x8946 TRILL RBridge Channel
from: https://datatracker.ietf.org/doc/html/rfc7042#appendix-B
そしてEthernet header のあとにEthernet Payloadが続く
Ethernet packet data: 16.bit: (ar$hrd) Hardware address space (e.g., Ethernet, Packet Radio Net.) 16.bit: (ar$pro) Protocol address space. For Ethernet hardware, this is from the set of type fields ether_typ$<protocol>. 8.bit: (ar$hln) byte length of each hardware address 8.bit: (ar$pln) byte length of each protocol address 16.bit: (ar$op) opcode (ares_op$REQUEST | ares_op$REPLY) nbytes: (ar$sha) Hardware address of sender of this packet, n from the ar$hln field. mbytes: (ar$spa) Protocol address of sender of this packet, m from the ar$pln field. nbytes: (ar$tha) Hardware address of target of this packet (if known). mbytes: (ar$tpa) Protocol address of target.
Hardware address space (ar$hrd) には Ethernet (10Mb) を表す Hardware Types である0x0001
を使用。
Number Hardware Type (hrd) Reference 0 Reserved [RFC5494] 1 Ethernet (10Mb) [Jon_Postel] 2 Experimental Ethernet (3Mb) [Jon_Postel] . .
Protocol address space (ar$pro) には IPv4 を表すEthertypes である 0x0800
を使用。
アルゴリズム
RFCより引用
?Do I have the hardware type in ar$hrd? Yes: (almost definitely) [optionally check the hardware length ar$hln] ?Do I speak the protocol in ar$pro? Yes: [optionally check the protocol length ar$pln] Merge_flag := false If the pair <protocol type, sender protocol address> is already in my translation table, update the sender hardware address field of the entry with the new information in the packet and set Merge_flag to true. ?Am I the target protocol address? Yes: If Merge_flag is false, add the triplet <protocol type, sender protocol address, sender hardware address> to the translation table. ?Is the opcode ares_op$REQUEST? (NOW look at the opcode!!) Yes: Swap hardware and protocol fields, putting the local hardware and protocol addresses in the sender fields. Set the ar$op field to ares_op$REPLY Send the packet to the (new) target hardware address on the same hardware on which the request was received.
日本語に訳すと以下
?ハードウェアの種類はar$hrdにありますか? はい:(ほぼ間違いなくEthernet) [オプションでハードウェアの長さar$hlnを確認する] 。 ?ar$proで指定されたプロトコル(IPv4)を話しているか? はい: [オプションでプロトコルの長さを確認するar$pln]。 Merge_flag := false <protocol type, sender protocol address>のペアが すでに変換テーブルにある場合、パケットの新しい情報でエントリ の送信者ハードウェアアドレスフィールドを更新し、 Merge_flagをtrueに設定する。 ?私はターゲットプロトコルアドレスですか? はい: Merge_flag が false の場合、<protocol type, 送信者プロトコルアドレス, 送信者ハードウェアアドレス> を変換テーブルに追加する。 ?オペコードはares_op$REQUESTか? (今すぐオペコードを見よ!!) はい: ハードウェアとプロトコルのフィールドを入れ替え、 ローカルハードウェアとプロトコルのアドレスを送信者フィールドに入れる。 ar$opフィールドをairs_op$REPLYに設定する。 要求を受けたハードウェアと同じハードウェア上の(新しい) ターゲット・ハードウェア・アドレスにパケットを送信する。
上記をコードにすると以下のようである。 コードはmicrops から github.com
static void arp_input(const uint8_t *data, size_t len, struct net_device *dev) { struct arp_ether_ip *msg; ip_addr_t spa, tpa; int merge = 0; struct net_iface *iface; if (len < sizeof(*msg)) { errorf("too short"); return; } msg = (struct arp_ether_ip *)data; // ハードウェアアドレスのチェック if (ntoh16(msg->hdr.hrd) != ARP_HRD_ETHER || msg->hdr.hln != ETHER_ADDR_LEN) { errorf("unsupported hardware address"); return; } // プロトコルアドレスのチェック if (ntoh16(msg->hdr.pro) != ARP_PRO_IP || msg->hdr.pln != IP_ADDR_LEN) { errorf("unsupported protocol address"); return; } memcpy(&spa, msg->spa, sizeof(spa)); memcpy(&tpa, msg->tpa, sizeof(tpa)); if (arp_cache_update(spa, msg->sha)) { /* updated */ merge = 1; } // デバイスに紐づくIPインタフェースを取得する iface = net_device_get_iface(dev, NET_IFACE_FAMILY_IP); // ARP要求のターゲットプロトコルアドレスと一致するか確認 if (iface && ((struct ip_iface *)iface)->unicast == tpa) { if (!merge) { arp_cache_insert(spa, msg->sha); } if (ntoh16(msg->hdr.op) == ARP_OP_REQUEST) { arp_reply(iface, msg->sha, spa, msg->sha); } } }
KLab camp の TCP/IP 自作キャンプに参加してARP のRFCを読もうと思った時のまとめ。 その時の資料は以下から