PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/os/net/src/arp.cpp

http://es-operating-system.googlecode.com/
C++ | 469 lines | 350 code | 79 blank | 40 comment | 18 complexity | ec94a73776390ca83754d264a33ca585 MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright 2008, 2009 Google Inc.
  3. * Copyright 2006, 2007 Nintendo Co., Ltd.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include <string.h>
  18. #include <new>
  19. #include <es/handle.h>
  20. #include <es/net/dix.h>
  21. #include "inet4.h"
  22. ARPFamily::ARPFamily(InFamily* inFamily) :
  23. inFamily(inFamily),
  24. scopeMux(&scopeAccessor, &scopeFactory),
  25. arpReceiver(inFamily),
  26. arpFactory(&arpAdapter),
  27. arpMux(&arpAccessor, &arpFactory)
  28. {
  29. ASSERT(inFamily);
  30. arpProtocol.setReceiver(&arpReceiver);
  31. arpAdapter.setReceiver(&inFamily->addressAny);
  32. Conduit::connectAA(&scopeMux, &arpProtocol);
  33. Conduit::connectBA(&arpProtocol, &arpMux);
  34. Socket::addAddressFamily(this);
  35. }
  36. // StateInit
  37. void Inet4Address::
  38. StateInit::start(Inet4Address* a)
  39. {
  40. // Install ARP cache for this address.
  41. a->inFamily->arpFamily.addAddress(a);
  42. a->setState(stateIncomplete);
  43. a->run(); // Invoke expired
  44. }
  45. bool Inet4Address::
  46. StateInit::input(InetMessenger* m, Inet4Address* a)
  47. {
  48. return true;
  49. }
  50. bool Inet4Address::
  51. StateInit::output(InetMessenger* m, Inet4Address* a)
  52. {
  53. return true;
  54. }
  55. bool Inet4Address::
  56. StateInit::error(InetMessenger* m, Inet4Address* a)
  57. {
  58. return true;
  59. }
  60. // StateIncomplete
  61. void Inet4Address::
  62. StateIncomplete::expired(Inet4Address* a)
  63. {
  64. // Send request
  65. if (++a->timeoutCount <= 6)
  66. {
  67. esReport("StateIncomplete::timeoutCount: %d\n", a->timeoutCount);
  68. Handle<Inet4Address> src = a->inFamily->selectSourceAddress(a);
  69. if (!src)
  70. {
  71. a->setState(stateInit);
  72. return;
  73. }
  74. int len = sizeof(DIXHdr) + sizeof(ARPHdr);
  75. Handle<InetMessenger> m = new InetMessenger(&InetReceiver::output, len, sizeof(DIXHdr));
  76. m->setScopeID(a->getScopeID());
  77. ARPHdr* arphdr = static_cast<ARPHdr*>(m->fix(sizeof(ARPHdr)));
  78. memset(arphdr, 0, sizeof(ARPHdr));
  79. arphdr->tpa = a->getAddress();
  80. arphdr->spa = src->getAddress();
  81. src->getMacAddress(arphdr->sha);
  82. arphdr->op = htons(ARPHdr::OP_REQUEST);
  83. Visitor v(m);
  84. a->adapter->accept(&v);
  85. a->alarm(5000000LL << a->timeoutCount);
  86. }
  87. else
  88. {
  89. // Not found:
  90. a->setState(stateInit);
  91. }
  92. }
  93. bool Inet4Address::
  94. StateIncomplete::input(InetMessenger* m, Inet4Address* a)
  95. {
  96. return true;
  97. }
  98. bool Inet4Address::
  99. StateIncomplete::output(InetMessenger* m, Inet4Address* a)
  100. {
  101. return true;
  102. }
  103. bool Inet4Address::
  104. StateIncomplete::error(InetMessenger* m, Inet4Address* a)
  105. {
  106. return true;
  107. }
  108. // StateReachable
  109. void Inet4Address::
  110. StateReachable::start(Inet4Address* a)
  111. {
  112. a->alarm(20 * 60 * 10000000LL);
  113. // Send kept packets
  114. while (Handle<InetMessenger> m = a->retrieve())
  115. {
  116. Visitor v(m);
  117. Conduit* conduit = &a->inFamily->scopeMux;
  118. conduit->accept(&v, conduit->getA());
  119. }
  120. }
  121. void Inet4Address::
  122. StateReachable::expired(Inet4Address* a)
  123. {
  124. a->setState(stateProbe);
  125. }
  126. bool Inet4Address::
  127. StateReachable::input(InetMessenger* m, Inet4Address* a)
  128. {
  129. return true;
  130. }
  131. bool Inet4Address::
  132. StateReachable::output(InetMessenger* m, Inet4Address* a)
  133. {
  134. return true;
  135. }
  136. bool Inet4Address::
  137. StateReachable::error(InetMessenger* m, Inet4Address* a)
  138. {
  139. return true;
  140. }
  141. // StateProbe
  142. void Inet4Address::
  143. StateProbe::expired(Inet4Address* a)
  144. {
  145. // Send probe
  146. if (++a->timeoutCount <= 6)
  147. {
  148. esReport("StateProbe::timeoutCount: %d\n", a->timeoutCount);
  149. Handle<Inet4Address> src = a->inFamily->selectSourceAddress(a);
  150. if (!src)
  151. {
  152. a->setState(stateInit);
  153. return;
  154. }
  155. int len = sizeof(DIXHdr) + sizeof(ARPHdr);
  156. Handle<InetMessenger> m = new InetMessenger(&InetReceiver::output, len, sizeof(DIXHdr));
  157. m->setScopeID(a->getScopeID());
  158. ARPHdr* arphdr = static_cast<ARPHdr*>(m->fix(sizeof(ARPHdr)));
  159. memset(arphdr, 0, sizeof(ARPHdr));
  160. arphdr->tpa = a->getAddress();
  161. a->getMacAddress(arphdr->tha); // Send directly to tha
  162. arphdr->spa = src->getAddress();
  163. src->getMacAddress(arphdr->sha);
  164. arphdr->op = htons(ARPHdr::OP_REQUEST);
  165. Visitor v(m);
  166. a->adapter->accept(&v);
  167. a->alarm(5000000LL << a->timeoutCount);
  168. }
  169. else
  170. {
  171. // Not found:
  172. a->setState(stateInit);
  173. // Uninstall ARP cache for this address.
  174. a->inFamily->arpFamily.removeAddress(a);
  175. }
  176. }
  177. bool Inet4Address::
  178. StateProbe::input(InetMessenger* m, Inet4Address* a)
  179. {
  180. return true;
  181. }
  182. bool Inet4Address::
  183. StateProbe::output(InetMessenger* m, Inet4Address* a)
  184. {
  185. return true;
  186. }
  187. bool Inet4Address::
  188. StateProbe::error(InetMessenger* m, Inet4Address* a)
  189. {
  190. return true;
  191. }
  192. // StateTentative
  193. void Inet4Address::
  194. StateTentative::start(Inet4Address* a)
  195. {
  196. // Set the interface MAC address to this address.
  197. NetworkInterface* nic = Socket::getInterface(a->getScopeID());
  198. ASSERT(nic);
  199. u8 mac[6];
  200. nic->getMacAddress(mac);
  201. a->setMacAddress(mac);
  202. // Install ARP cache for this address.
  203. a->inFamily->arpFamily.addAddress(a);
  204. a->alarm(rand48() % (ARPHdr::PROBE_WAIT * 10000000LL));
  205. }
  206. void Inet4Address::
  207. StateTentative::expired(Inet4Address* a)
  208. {
  209. ASSERT(a->adapter);
  210. if (++a->timeoutCount <= ARPHdr::PROBE_NUM)
  211. {
  212. esReport("StateTentative::timeoutCount: %d\n", a->timeoutCount);
  213. // Send probe
  214. int len = sizeof(DIXHdr) + sizeof(ARPHdr);
  215. Handle<InetMessenger> m = new InetMessenger(&InetReceiver::output, len, sizeof(DIXHdr));
  216. m->setScopeID(a->getScopeID());
  217. ARPHdr* arphdr = static_cast<ARPHdr*>(m->fix(sizeof(ARPHdr)));
  218. memset(arphdr, 0, sizeof(ARPHdr));
  219. arphdr->tpa = a->getAddress();
  220. arphdr->spa = InAddrAny;
  221. a->getMacAddress(arphdr->sha);
  222. arphdr->op = htons(ARPHdr::OP_REQUEST);
  223. Visitor v(m);
  224. a->adapter->accept(&v);
  225. if (a->timeoutCount < ARPHdr::PROBE_NUM)
  226. {
  227. a->alarm(ARPHdr::PROBE_MIN * 10000000LL + rand48() % (ARPHdr::PROBE_MAX * 10000000LL));
  228. }
  229. else
  230. {
  231. a->alarm(ARPHdr::ANNOUNCE_WAIT * 10000000LL);
  232. }
  233. }
  234. else
  235. {
  236. a->setState(statePreferred);
  237. a->start();
  238. a->run();
  239. }
  240. }
  241. bool Inet4Address::
  242. StateTentative::input(InetMessenger* m, Inet4Address* a)
  243. {
  244. return true;
  245. }
  246. bool Inet4Address::
  247. StateTentative::output(InetMessenger* m, Inet4Address* a)
  248. {
  249. return true;
  250. }
  251. bool Inet4Address::
  252. StateTentative::error(InetMessenger* m, Inet4Address* a)
  253. {
  254. return true;
  255. }
  256. // StatePreferred
  257. void Inet4Address::
  258. StatePreferred::start(Inet4Address* a)
  259. {
  260. // Install an ICMP echo request adapter for this address.
  261. InetMessenger m;
  262. m.setLocal(a);
  263. Installer installer(&m);
  264. a->inFamily->echoRequestMux.accept(&installer, &a->inFamily->icmpMux);
  265. }
  266. void Inet4Address::
  267. StatePreferred::expired(Inet4Address* a)
  268. {
  269. ASSERT(a->adapter);
  270. if (++a->timeoutCount <= ARPHdr::ANNOUNCE_NUM)
  271. {
  272. esReport("StatePreferred::timeoutCount: %d\n", a->timeoutCount);
  273. // Send announcement
  274. int len = sizeof(DIXHdr) + sizeof(ARPHdr);
  275. Handle<InetMessenger> m = new InetMessenger(&InetReceiver::output, len, sizeof(DIXHdr));
  276. m->setScopeID(a->getScopeID());
  277. ARPHdr* arphdr = static_cast<ARPHdr*>(m->fix(sizeof(ARPHdr)));
  278. memset(arphdr, 0, sizeof(ARPHdr));
  279. arphdr->tpa = a->getAddress();
  280. a->getMacAddress(arphdr->tha);
  281. arphdr->spa = a->getAddress();;
  282. a->getMacAddress(arphdr->sha);
  283. arphdr->op = htons(ARPHdr::OP_REQUEST);
  284. Visitor v(m);
  285. a->adapter->accept(&v);
  286. a->alarm(ARPHdr::ANNOUNCE_INTERVAL * 10000000LL);
  287. }
  288. }
  289. bool Inet4Address::
  290. StatePreferred::input(InetMessenger* m, Inet4Address* a)
  291. {
  292. ARPHdr* arphdr = static_cast<ARPHdr*>(m->fix(sizeof(ARPHdr)));
  293. if (ntohs(arphdr->op) == ARPHdr::OP_REQUEST)
  294. {
  295. esReport("StatePreferred::input: %02x:%02x:%02x:%02x:%02x:%02x\n",
  296. arphdr->tha[0], arphdr->tha[1], arphdr->tha[2],
  297. arphdr->tha[3], arphdr->tha[4], arphdr->tha[5]);
  298. // Send reply
  299. int len = sizeof(DIXHdr) + sizeof(ARPHdr);
  300. Handle<InetMessenger> r = new InetMessenger(&InetReceiver::output, len, sizeof(DIXHdr));
  301. r->setScopeID(a->getScopeID());
  302. ARPHdr* rephdr = static_cast<ARPHdr*>(r->fix(sizeof(ARPHdr)));
  303. memset(rephdr, 0, sizeof(ARPHdr));
  304. rephdr->tpa = arphdr->spa;
  305. memmove(rephdr->tha, arphdr->sha, 6);
  306. rephdr->spa = a->getAddress();;
  307. a->getMacAddress(rephdr->sha);
  308. rephdr->op = htons(ARPHdr::OP_REPLY);
  309. Visitor v(r);
  310. a->adapter->accept(&v);
  311. }
  312. return true;
  313. }
  314. bool Inet4Address::
  315. StatePreferred::output(InetMessenger* m, Inet4Address* a)
  316. {
  317. return true;
  318. }
  319. bool Inet4Address::
  320. StatePreferred::error(InetMessenger* m, Inet4Address* a)
  321. {
  322. return true;
  323. }
  324. // StateDeprecated
  325. void Inet4Address::
  326. StateDeprecated::start(Inet4Address* a)
  327. {
  328. // Uninstall ARP cache for this address.
  329. a->inFamily->arpFamily.removeAddress(a);
  330. // Install an ICMP echo request adapter for this address if necessary.
  331. InetMessenger m;
  332. m.setLocal(a);
  333. void* key = a->inFamily->echoRequestMux.getKey(&m);
  334. Adapter* adapter = dynamic_cast<Adapter*>(a->inFamily->echoRequestMux.getB(key));
  335. if (adapter)
  336. {
  337. Uninstaller uninstaller(&m);
  338. adapter->accept(&uninstaller);
  339. }
  340. }
  341. bool Inet4Address::
  342. StateDeprecated::input(InetMessenger* m, Inet4Address* a)
  343. {
  344. return true;
  345. }
  346. bool Inet4Address::
  347. StateDeprecated::output(InetMessenger* m, Inet4Address* a)
  348. {
  349. return true;
  350. }
  351. bool Inet4Address::
  352. StateDeprecated::error(InetMessenger* m, Inet4Address* a)
  353. {
  354. return true;
  355. }
  356. // ARPReceiver
  357. bool ARPReceiver::
  358. input(InetMessenger* m, Conduit* c)
  359. {
  360. ASSERT(m);
  361. // Validates the received ARP packet.
  362. ARPHdr* arphdr = static_cast<ARPHdr*>(m->fix(sizeof(ARPHdr)));
  363. if (ntohs(arphdr->hrd) != ARPHdr::HRD_ETHERNET ||
  364. ntohs(arphdr->pro) != ARPHdr::PRO_IP ||
  365. arphdr->hln != 6 ||
  366. arphdr->pln != 4)
  367. {
  368. return false;
  369. }
  370. m->setType(AF_ARP);
  371. Handle<Inet4Address> addr;
  372. addr = inFamily->getAddress(arphdr->spa, m->getScopeID());
  373. if (addr)
  374. {
  375. addr->setMacAddress(arphdr->sha);
  376. addr->cancel();
  377. if (addr->isLocalAddress())
  378. {
  379. addr->setState(Inet4Address::stateDeprecated);
  380. }
  381. else
  382. {
  383. addr->setState(Inet4Address::stateReachable);
  384. }
  385. addr->start(); // To send waiting packets.
  386. }
  387. addr = inFamily->getAddress(arphdr->tpa, m->getScopeID());
  388. m->setLocal(addr);
  389. return true;
  390. }