improvements and fixes in arp protocol and rtl8139 driver code
[quarnos.git] / resources / net / arp.cpp
blob6b2913f82b6ddd045728c1cfa7e9a1d2e5863c19
1 #include "arp.h"
2 #include "mac_addr.h"
4 using namespace net;
6 void poll(volatile bool *value) {
7 while (!*value) asm volatile("hlt");
10 mac_addr arp::get_haddr(const ipv4_addr &ipaddr) {
11 p<arp_table::arp_record> rec = table->get(ipaddr);
12 if (rec.valid())
13 return rec->haddr;
15 p<arp_packet> pkg = new arp_packet;
17 pkg->htype = to_be16(ethernet);
18 pkg->ptype = to_be16(ipv4);
20 pkg->hlen = mac_addr::in_bytes();
21 pkg->plen = ipv4_addr::in_bytes();
23 pkg->oper = to_be16(request);
25 pkg->sha0 = my_haddr.first_be32();
26 pkg->sha1 = my_haddr.last_be16();
27 pkg->spa = my_paddr.to_be();
29 pkg->tha0 = 0;
30 pkg->tha1 = 0;
31 pkg->tpa = ipaddr.to_be();
33 mac_addr broadcast = mac_addr::from_be(0xffffffff, 0xffff);
34 down->send_data(broadcast, et_arp, buffer::to_mem(pkg));
36 pkg.dispose();
38 rec = p<arp_table::arp_record>::invalid;
40 do {
41 poll(&received);
42 rec = table->get(ipaddr);
43 } while (!rec.valid());
45 return rec->haddr;
49 void arp::receive_packet(p<arp_packet> pkg) {
50 if (from_be16(pkg->oper) == request) {
51 if (ipv4_addr::from_be(pkg->tpa) != my_paddr)
52 return;
54 mac_addr mac = mac_addr::from_be(pkg->sha0, pkg->sha1);
56 p<arp_packet> rpl = new arp_packet;
58 rpl->htype = pkg->htype;
59 rpl->ptype = pkg->ptype;
61 rpl->hlen = pkg->hlen;
62 rpl->plen = pkg->plen;
64 rpl->oper = to_be16(reply);
66 rpl->sha0 = my_haddr.first_be32();
67 rpl->sha1 = my_haddr.last_be16();
68 rpl->spa = my_paddr.to_be();
70 rpl->tha0 = mac.first_be16();
71 rpl->tha1 = mac.last_be32();
72 rpl->tpa = pkg->spa;
74 down->send_data(mac, et_arp, buffer::to_mem(rpl));
76 rpl.dispose();
78 } else if (from_be16(pkg->oper) == reply) {
79 p<arp_table::arp_record> rec = new arp_table::arp_record;
80 rec->prot = from_be16(pkg->ptype);
81 rec->paddr = ipv4_addr::from_be(pkg->spa);
82 rec->haddr = mac_addr::from_be(pkg->sha0, pkg->sha1);
84 table->add(rec);
85 received = true;
90 void arp::receive_data(const buffer &x) {
91 receive_packet(x.cast<arp_packet>());