net: arp packet builder and interpreter
[quarnos.git] / resources / net / arp.cpp
blob96ff36ab1563779ae8cbdbb5e4ac10a37fde88d0
1 #include "arp.h"
2 #include "mac_addr.h"
3 #include "arp_packet.h"
5 using namespace net;
7 void poll(volatile bool *value) {
8 while (!*value) asm volatile("nop");
11 mac_addr arp::get_haddr(const ipv4_addr &ipaddr) {
12 p<arp_table::arp_record> rec = table.get(ipaddr);
13 if (rec.valid())
14 return rec->haddr;
16 p<arp_packet> pkg = new arp_packet;
17 pkg->set_ptype(arp_packet::p_ipv4);
18 pkg->set_htype(arp_packet::h_ethernet);
20 pkg->set_type(arp_packet::arp_request);
22 pkg->set_source_haddr(my_haddr);
23 pkg->set_source_paddr(my_paddr);
25 pkg->set_target_paddr(ipaddr);
27 mac_addr broadcast = mac_addr::from_be(0xffffffff, 0xffff);
28 down->send_data(broadcast, et_arp, pkg->generate());
30 pkg.dispose();
32 rec = p<arp_table::arp_record>::invalid;
34 do {
35 poll(&received);
36 received = false;
38 rec = table.get(ipaddr);
39 } while (!rec.valid());
41 return rec->haddr;
44 void arp::receive_packet(p<arp_packet> pkg) {
45 if (pkg->get_type() == arp_packet::arp_request) {
46 if (pkg->get_target_paddr() != my_paddr)
47 return;
49 /* Add sender to ARP table */
50 arp_table::arp_record rec;
51 rec.prot = pkg->get_ptype();
52 rec.paddr = pkg->get_source_paddr();
53 rec.haddr = pkg->get_source_haddr();
55 table.add(rec);
57 p<arp_packet> rpl = new arp_packet;
59 rpl->set_htype(pkg->get_htype());
60 rpl->set_ptype(pkg->get_ptype());
62 rpl->set_type(arp_packet::arp_reply);
64 rpl->set_source_haddr(my_haddr);
65 rpl->set_source_paddr(my_paddr);
67 rpl->set_target_haddr(pkg->get_source_haddr());
68 rpl->set_target_paddr(pkg->get_source_paddr());
70 down->send_data(pkg->get_source_haddr(), et_arp, rpl->generate());
72 rpl.dispose();
74 } else if (pkg->get_type() == arp_packet::arp_reply) {
75 arp_table::arp_record rec;
76 rec.prot = pkg->get_ptype();
77 rec.paddr = pkg->get_source_paddr();
78 rec.haddr = pkg->get_source_haddr();
80 table.add(rec);
81 received = true;
85 void arp::receive_data(const buffer &x) {
86 receive_packet(new arp_packet(x));