SessionManager.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. */
  15. #include "memory/Allocator.h"
  16. #include "wire/PFChan.h"
  17. #include "net/SessionManager.h"
  18. #include "crypto/AddressCalc.h"
  19. #include "util/AddrTools.h"
  20. #include "wire/Error.h"
  21. #include "util/events/Time.h"
  22. #include "util/Defined.h"
  23. #include "wire/RouteHeader.h"
  24. #include "util/events/Timeout.h"
  25. #include "util/Checksum.h"
  26. #include "wire/Metric.h"
  27. /** Handle numbers 0-3 are reserved for CryptoAuth nonces. */
  28. #define MIN_FIRST_HANDLE 4
  29. #define MAX_FIRST_HANDLE 100000
  30. struct BufferedMessage
  31. {
  32. struct Message* msg;
  33. struct Allocator* alloc;
  34. uint64_t timeSentMilliseconds;
  35. };
  36. struct Ip6 {
  37. uint8_t bytes[16];
  38. };
  39. #define Map_KEY_TYPE struct Ip6
  40. #define Map_VALUE_TYPE struct BufferedMessage*
  41. #define Map_NAME BufferedMessages
  42. #include "util/Map.h"
  43. #define Map_KEY_TYPE struct Ip6
  44. #define Map_VALUE_TYPE struct SessionManager_Session_pvt*
  45. #define Map_NAME OfSessionsByIp6
  46. #define Map_ENABLE_HANDLES
  47. #include "util/Map.h"
  48. struct SessionManager_pvt
  49. {
  50. struct SessionManager pub;
  51. struct Iface eventIf;
  52. struct Allocator* alloc;
  53. struct Map_BufferedMessages bufMap;
  54. struct Map_OfSessionsByIp6 ifaceMap;
  55. struct Log* log;
  56. struct CryptoAuth* cryptoAuth;
  57. struct EventBase* eventBase;
  58. uint32_t firstHandle;
  59. Identity
  60. };
  61. struct SessionManager_Session_pvt
  62. {
  63. struct SessionManager_Session pub;
  64. struct SessionManager_pvt* sessionManager;
  65. struct Allocator* alloc;
  66. bool foundKey;
  67. Identity
  68. };
  69. #define debugHandlesAndLabel(logger, session, label, message, ...) \
  70. do { \
  71. if (!Defined(Log_DEBUG)) { break; } \
  72. uint8_t path[20]; \
  73. AddrTools_printPath(path, label); \
  74. uint8_t ip[40]; \
  75. AddrTools_printIp(ip, session->pub.caSession->herIp6); \
  76. Log_debug(logger, "ver[%u] send[%d] recv[%u] ip[%s] path[%s] " message, \
  77. session->pub.version, \
  78. session->pub.sendHandle, \
  79. session->pub.receiveHandle, \
  80. ip, \
  81. path, \
  82. __VA_ARGS__); \
  83. } while (0)
  84. //CHECKFILES_IGNORE expecting a ;
  85. #define debugHandlesAndLabel0(logger, session, label, message) \
  86. debugHandlesAndLabel(logger, session, label, "%s", message)
  87. #define debugSession(logger, session, message, ...) \
  88. do { \
  89. if (!Defined(Log_DEBUG)) { break; } \
  90. uint8_t sendPath[20]; \
  91. uint8_t recvPath[20]; \
  92. uint8_t ip[40]; \
  93. AddrTools_printPath(sendPath, (session)->pub.sendSwitchLabel); \
  94. AddrTools_printPath(recvPath, (session)->pub.recvSwitchLabel); \
  95. AddrTools_printIp(ip, (session)->pub.caSession->herIp6); \
  96. Log_debug((logger), "Session[%p] sendPath[%s] recvPath[%s] ip[%s] " message, \
  97. (void*)session, \
  98. sendPath, \
  99. recvPath, \
  100. ip, \
  101. __VA_ARGS__); \
  102. } while (0)
  103. //CHECKFILES_IGNORE ;
  104. #define debugSession0(logger, session, message) \
  105. debugSession(logger, session, "%s", message)
  106. static void sendSession(struct SessionManager_Session_pvt* sess,
  107. uint64_t path,
  108. uint32_t destPf,
  109. enum PFChan_Core ev)
  110. {
  111. struct PFChan_Node session = {
  112. .path_be = Endian_hostToBigEndian64(path),
  113. .metric_be = Endian_bigEndianToHost32(sess->pub.metric),
  114. .version_be = Endian_hostToBigEndian32(sess->pub.version)
  115. };
  116. Bits_memcpy(session.ip6, sess->pub.caSession->herIp6, 16);
  117. Bits_memcpy(session.publicKey, sess->pub.caSession->herPublicKey, 32);
  118. struct Allocator* alloc = Allocator_child(sess->alloc);
  119. struct Message* msg = Message_new(0, PFChan_Node_SIZE + 512, alloc);
  120. Er_assert(Message_epush(msg, &session, PFChan_Node_SIZE));
  121. Er_assert(Message_epush32be(msg, destPf));
  122. Er_assert(Message_epush32be(msg, ev));
  123. Iface_send(&sess->sessionManager->eventIf, msg);
  124. Allocator_free(alloc);
  125. }
  126. static inline void check(struct SessionManager_pvt* sm, int mapIndex)
  127. {
  128. struct SessionManager_Session_pvt* ssp = Identity_check(sm->ifaceMap.values[mapIndex]);
  129. if (ssp->foundKey) { return; }
  130. uint8_t* herPubKey = ssp->pub.caSession->herPublicKey;
  131. if (!Bits_isZero(herPubKey, 32)) {
  132. uint8_t ip6[16];
  133. AddressCalc_addressForPublicKey(ip6, herPubKey);
  134. Assert_true(!Bits_memcmp(&sm->ifaceMap.keys[mapIndex], ip6, 16));
  135. ssp->foundKey = true;
  136. }
  137. }
  138. static inline struct SessionManager_Session_pvt* sessionForHandle(uint32_t handle,
  139. struct SessionManager_pvt* sm)
  140. {
  141. int index = Map_OfSessionsByIp6_indexForHandle(handle - sm->firstHandle, &sm->ifaceMap);
  142. if (index < 0) { return NULL; }
  143. check(sm, index);
  144. return Identity_check(sm->ifaceMap.values[index]);
  145. }
  146. struct SessionManager_Session* SessionManager_sessionForHandle(uint32_t handle,
  147. struct SessionManager* manager)
  148. {
  149. struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) manager);
  150. return (struct SessionManager_Session*) sessionForHandle(handle, sm);
  151. }
  152. static inline struct SessionManager_Session_pvt* sessionForIp6(uint8_t ip6[16],
  153. struct SessionManager_pvt* sm)
  154. {
  155. int ifaceIndex = Map_OfSessionsByIp6_indexForKey((struct Ip6*)ip6, &sm->ifaceMap);
  156. if (ifaceIndex == -1) { return NULL; }
  157. check(sm, ifaceIndex);
  158. return Identity_check(sm->ifaceMap.values[ifaceIndex]);
  159. }
  160. struct SessionManager_Session* SessionManager_sessionForIp6(uint8_t* ip6,
  161. struct SessionManager* manager)
  162. {
  163. struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) manager);
  164. return (struct SessionManager_Session*) sessionForIp6(ip6, sm);
  165. }
  166. struct SessionManager_HandleList* SessionManager_getHandleList(struct SessionManager* manager,
  167. struct Allocator* alloc)
  168. {
  169. struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) manager);
  170. struct SessionManager_HandleList* out =
  171. Allocator_calloc(alloc, sizeof(struct SessionManager_HandleList), 1);
  172. uint32_t* buff = Allocator_calloc(alloc, 4, sm->ifaceMap.count);
  173. out->length = sm->ifaceMap.count;
  174. out->handles = buff;
  175. for (int i = 0; i < out->length; i++) {
  176. buff[i] = sm->ifaceMap.handles[i] + sm->firstHandle;
  177. }
  178. return out;
  179. }
  180. static struct SessionManager_Session_pvt* getSession(struct SessionManager_pvt* sm,
  181. uint8_t ip6[16],
  182. uint8_t pubKey[32],
  183. uint32_t version,
  184. uint64_t label,
  185. uint32_t metric)
  186. {
  187. Assert_true(AddressCalc_validAddress(ip6));
  188. struct SessionManager_Session_pvt* sess = sessionForIp6(ip6, sm);
  189. if (sess) {
  190. sess->pub.version = (sess->pub.version) ? sess->pub.version : version;
  191. if (metric == Metric_DEAD_LINK) {
  192. // this is a broken path
  193. if (sess->pub.sendSwitchLabel == label) {
  194. debugSession0(sm->log, sess, "broken path");
  195. if (sess->pub.sendSwitchLabel == sess->pub.recvSwitchLabel) {
  196. sess->pub.sendSwitchLabel = 0;
  197. sess->pub.metric = Metric_DEAD_LINK;
  198. } else {
  199. sess->pub.sendSwitchLabel = sess->pub.recvSwitchLabel;
  200. sess->pub.metric = Metric_SM_INCOMING;
  201. }
  202. }
  203. } else if (metric <= sess->pub.metric && label) {
  204. if (sess->pub.sendSwitchLabel != label) {
  205. debugSession0(sm->log, sess, "discovered path");
  206. }
  207. sess->pub.sendSwitchLabel = label;
  208. sess->pub.version = (version) ? version : sess->pub.version;
  209. sess->pub.metric = metric;
  210. }
  211. return sess;
  212. }
  213. struct Allocator* alloc = Allocator_child(sm->alloc);
  214. sess = Allocator_calloc(alloc, sizeof(struct SessionManager_Session_pvt), 1);
  215. Identity_set(sess);
  216. sess->pub.caSession = CryptoAuth_newSession(sm->cryptoAuth, alloc, pubKey, false, "inner");
  217. sess->foundKey = !Bits_isZero(pubKey, 32);
  218. if (sess->foundKey) {
  219. uint8_t realIp6[16];
  220. AddressCalc_addressForPublicKey(realIp6, pubKey);
  221. Assert_true(!Bits_memcmp(realIp6, ip6, 16));
  222. }
  223. int ifaceIndex = Map_OfSessionsByIp6_put((struct Ip6*)ip6, &sess, &sm->ifaceMap);
  224. sess->pub.receiveHandle = sm->ifaceMap.handles[ifaceIndex] + sm->firstHandle;
  225. if (Defined(Log_DEBUG)) {
  226. uint8_t printedIp6[40];
  227. AddrTools_printIp(printedIp6, ip6);
  228. Log_debug(sm->log, "Created session for [%s] handle [%u]",
  229. printedIp6, sess->pub.receiveHandle);
  230. }
  231. sess->alloc = alloc;
  232. sess->sessionManager = sm;
  233. sess->pub.version = version;
  234. sess->pub.timeOfLastIncoming = Time_currentTimeMilliseconds(sm->eventBase);
  235. sess->pub.sendSwitchLabel = label;
  236. sess->pub.metric = metric;
  237. //Allocator_onFree(alloc, sessionCleanup, sess);
  238. sendSession(sess, label, 0xffffffff, PFChan_Core_SESSION);
  239. check(sm, ifaceIndex);
  240. return sess;
  241. }
  242. static Iface_DEFUN ctrlFrame(struct Message* msg, struct SessionManager_pvt* sm)
  243. {
  244. struct RouteHeader rh;
  245. Bits_memset(&rh, 0, RouteHeader_SIZE);
  246. Er_assert(Message_epop(msg, &rh.sh, SwitchHeader_SIZE));
  247. Er_assert(Message_epop(msg, NULL, 4));
  248. rh.flags = RouteHeader_flags_INCOMING | RouteHeader_flags_CTRLMSG;
  249. Er_assert(Message_epush(msg, &rh, RouteHeader_SIZE));
  250. return Iface_next(&sm->pub.insideIf, msg);
  251. }
  252. static Iface_DEFUN failedDecrypt(struct Message* msg,
  253. uint64_t label_be,
  254. struct SessionManager_pvt* sm)
  255. {
  256. Er_assert(Message_epush32be(msg, Error_AUTHENTICATION));
  257. Er_assert(Message_epush16be(msg, Control_ERROR));
  258. Er_assert(Message_epush16be(msg, 0));
  259. uint16_t csum = Checksum_engine(msg->bytes, msg->length);
  260. Er_assert(Message_epop16be(msg));
  261. Er_assert(Message_epush16be(msg, csum));
  262. Er_assert(Message_epush32be(msg, 0xffffffff));
  263. struct SwitchHeader sh;
  264. Bits_memset(&sh, 0, SwitchHeader_SIZE);
  265. SwitchHeader_setSuppressErrors(&sh, true);
  266. SwitchHeader_setVersion(&sh, SwitchHeader_CURRENT_VERSION);
  267. sh.label_be = label_be;
  268. Er_assert(Message_epush(msg, &sh, SwitchHeader_SIZE));
  269. return Iface_next(&sm->pub.switchIf, msg);
  270. }
  271. static Iface_DEFUN incomingFromSwitchIf(struct Message* msg, struct Iface* iface)
  272. {
  273. struct SessionManager_pvt* sm =
  274. Identity_containerOf(iface, struct SessionManager_pvt, pub.switchIf);
  275. // SwitchHeader, handle, 0 or more bytes of control frame
  276. if (msg->length < SwitchHeader_SIZE + 4) {
  277. Log_debug(sm->log, "DROP runt");
  278. return NULL;
  279. }
  280. struct SwitchHeader* switchHeader = (struct SwitchHeader*) msg->bytes;
  281. Er_assert(Message_eshift(msg, -SwitchHeader_SIZE));
  282. // The label comes in reversed from the switch because the switch doesn't know that we aren't
  283. // another switch ready to parse more bits, bit reversing the label yields the source address.
  284. // (the field is still big endian!)
  285. switchHeader->label_be = Bits_bitReverse64(switchHeader->label_be);
  286. struct SessionManager_Session_pvt* session;
  287. uint32_t nonceOrHandle = Endian_bigEndianToHost32(((uint32_t*)msg->bytes)[0]);
  288. if (nonceOrHandle == 0xffffffff) {
  289. Er_assert(Message_eshift(msg, SwitchHeader_SIZE));
  290. return ctrlFrame(msg, sm);
  291. }
  292. // handle, small cryptoAuth header
  293. if (msg->length < 4 + 20) {
  294. Log_debug(sm->log, "DROP runt");
  295. return NULL;
  296. }
  297. // This is for handling error situations and being able to send back some kind of a message.
  298. uint8_t firstSixteen[16];
  299. uint32_t length0 = msg->length;
  300. Assert_true(msg->length >= 16);
  301. Bits_memcpy(firstSixteen, msg->bytes, 16);
  302. if (nonceOrHandle > 3) {
  303. // > 3 it's a handle.
  304. session = sessionForHandle(nonceOrHandle, sm);
  305. if (!session) {
  306. Log_debug(sm->log, "DROP message with unrecognized handle [%u]", nonceOrHandle);
  307. return NULL;
  308. }
  309. Er_assert(Message_eshift(msg, -4));
  310. uint32_t nonce = Endian_bigEndianToHost32(((uint32_t*)msg->bytes)[0]);
  311. if (nonce < 4) {
  312. Log_debug(sm->log, "DROP setup message [%u] with specified handle [%u]",
  313. nonce, nonceOrHandle);
  314. return NULL;
  315. }
  316. } else {
  317. // handle + big cryptoauth header
  318. if (msg->length < CryptoHeader_SIZE + 4) {
  319. Log_debug(sm->log, "DROP runt");
  320. return NULL;
  321. }
  322. struct CryptoHeader* caHeader = (struct CryptoHeader*) msg->bytes;
  323. uint8_t ip6[16];
  324. // a packet which claims to be "from us" causes problems
  325. if (!AddressCalc_addressForPublicKey(ip6, caHeader->publicKey)) {
  326. Log_debug(sm->log, "DROP Handshake with non-fc key");
  327. return NULL;
  328. }
  329. if (!Bits_memcmp(caHeader->publicKey, sm->cryptoAuth->publicKey, 32)) {
  330. Log_debug(sm->log, "DROP Handshake from 'ourselves'");
  331. return NULL;
  332. }
  333. uint64_t label = Endian_bigEndianToHost64(switchHeader->label_be);
  334. session = getSession(sm, ip6, caHeader->publicKey, 0, label, Metric_SM_INCOMING);
  335. CryptoAuth_resetIfTimeout(session->pub.caSession);
  336. debugHandlesAndLabel(sm->log, session, label, "new session nonce[%d]", nonceOrHandle);
  337. }
  338. bool currentMessageSetup = (nonceOrHandle <= 3);
  339. enum CryptoAuth_DecryptErr ret = CryptoAuth_decrypt(session->pub.caSession, msg);
  340. if (ret) {
  341. debugHandlesAndLabel(sm->log, session,
  342. Endian_bigEndianToHost64(switchHeader->label_be),
  343. "DROP Failed decrypting message NoH[%d] state[%s]",
  344. nonceOrHandle,
  345. CryptoAuth_stateString(CryptoAuth_getState(session->pub.caSession)));
  346. Er_assert(Message_eshift(msg, length0 - msg->length - 24));
  347. msg->length = 0;
  348. Er_assert(Message_epush32be(msg, CryptoAuth_getState(session->pub.caSession)));
  349. Er_assert(Message_epush32be(msg, ret));
  350. Er_assert(Message_epush(msg, firstSixteen, 16));
  351. Er_assert(Message_eshift(msg, SwitchHeader_SIZE));
  352. Assert_true(msg->bytes == (uint8_t*)switchHeader);
  353. uint64_t label_be = switchHeader->label_be;
  354. switchHeader->label_be = Bits_bitReverse64(switchHeader->label_be);
  355. return failedDecrypt(msg, label_be, sm);
  356. }
  357. if (currentMessageSetup) {
  358. session->pub.sendHandle = Er_assert(Message_epop32be(msg));
  359. }
  360. Er_assert(Message_eshift(msg, RouteHeader_SIZE));
  361. struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
  362. Assert_true(msg->length >= DataHeader_SIZE);
  363. session->pub.bytesIn += msg->length;
  364. session->pub.timeOfLastIncoming = Time_currentTimeMilliseconds(sm->eventBase);
  365. if (currentMessageSetup) {
  366. Bits_memcpy(&header->sh, switchHeader, SwitchHeader_SIZE);
  367. debugHandlesAndLabel0(sm->log,
  368. session,
  369. Endian_bigEndianToHost64(switchHeader->label_be),
  370. "received start message");
  371. } else {
  372. // RouteHeader is laid out such that no copy of switch header should be needed.
  373. Assert_true(&header->sh == switchHeader);
  374. if (0) { // noisey
  375. debugHandlesAndLabel0(sm->log,
  376. session,
  377. Endian_bigEndianToHost64(switchHeader->label_be),
  378. "received run message");
  379. }
  380. }
  381. header->version_be = Endian_hostToBigEndian32(session->pub.version);
  382. Bits_memcpy(header->ip6, session->pub.caSession->herIp6, 16);
  383. Bits_memcpy(header->publicKey, session->pub.caSession->herPublicKey, 32);
  384. header->unused = 0;
  385. header->flags = RouteHeader_flags_INCOMING;
  386. uint64_t path = Endian_bigEndianToHost64(switchHeader->label_be);
  387. if (!session->pub.sendSwitchLabel) {
  388. session->pub.sendSwitchLabel = path;
  389. }
  390. if (path != session->pub.recvSwitchLabel) {
  391. session->pub.recvSwitchLabel = path;
  392. sendSession(session, path, 0xffffffff, PFChan_Core_DISCOVERED_PATH);
  393. }
  394. return Iface_next(&sm->pub.insideIf, msg);
  395. }
  396. static void checkTimedOutBuffers(struct SessionManager_pvt* sm)
  397. {
  398. for (int i = 0; i < (int)sm->bufMap.count; i++) {
  399. struct BufferedMessage* buffered = sm->bufMap.values[i];
  400. int64_t lag = Time_currentTimeMilliseconds(sm->eventBase) - buffered->timeSentMilliseconds;
  401. if (lag < 10000) { continue; }
  402. Map_BufferedMessages_remove(i, &sm->bufMap);
  403. Allocator_free(buffered->alloc);
  404. i--;
  405. }
  406. }
  407. static void unsetupSession(struct SessionManager_pvt* sm, struct SessionManager_Session_pvt* sess)
  408. {
  409. if (!sess->pub.version || !(sess->pub.sendSwitchLabel || sess->pub.recvSwitchLabel)) {
  410. // Nothing we can do here because it's not ok to send traffic without a version num.
  411. return;
  412. }
  413. struct Allocator* eventAlloc = Allocator_child(sm->alloc);
  414. struct Message* eventMsg = Message_new(0, 512, eventAlloc);
  415. struct PFChan_Node n = { .metric_be = Endian_hostToBigEndian32(Metric_DEAD_LINK) };
  416. n.path_be = Endian_hostToBigEndian64(sess->pub.sendSwitchLabel ?
  417. sess->pub.sendSwitchLabel : sess->pub.recvSwitchLabel);
  418. n.version_be = Endian_hostToBigEndian32(sess->pub.version);
  419. n.metric_be = Endian_bigEndianToHost32(sess->pub.metric);
  420. Bits_memcpy(n.publicKey, sess->pub.caSession->herPublicKey, 32);
  421. Bits_memcpy(n.ip6, sess->pub.caSession->herIp6, 16);
  422. Er_assert(Message_epush(eventMsg, &n, PFChan_Node_SIZE));
  423. Er_assert(Message_epush32be(eventMsg, 0xffffffff));
  424. Er_assert(Message_epush32be(eventMsg, PFChan_Core_UNSETUP_SESSION));
  425. Iface_send(&sm->eventIf, eventMsg);
  426. Allocator_free(eventAlloc);
  427. }
  428. static void triggerSearch(struct SessionManager_pvt* sm, uint8_t target[16], uint32_t version)
  429. {
  430. struct Allocator* eventAlloc = Allocator_child(sm->alloc);
  431. struct Message* eventMsg = Message_new(0, 512, eventAlloc);
  432. Er_assert(Message_epush32be(eventMsg, version));
  433. Er_assert(Message_epush32be(eventMsg, 0));
  434. Er_assert(Message_epush(eventMsg, target, 16));
  435. Er_assert(Message_epush32be(eventMsg, 0xffffffff));
  436. Er_assert(Message_epush32be(eventMsg, PFChan_Core_SEARCH_REQ));
  437. Iface_send(&sm->eventIf, eventMsg);
  438. Allocator_free(eventAlloc);
  439. }
  440. static void checkTimedOutSessions(struct SessionManager_pvt* sm)
  441. {
  442. for (int i = (int)sm->ifaceMap.count - 1; i >= 0; i--) {
  443. struct SessionManager_Session_pvt* sess = sm->ifaceMap.values[i];
  444. int64_t now = Time_currentTimeMilliseconds(sm->eventBase);
  445. // Check if the session is timed out...
  446. if (now - sess->pub.timeOfLastIncoming > sm->pub.sessionTimeoutMilliseconds) {
  447. debugSession0(sm->log, sess, "ended");
  448. sendSession(sess, sess->pub.sendSwitchLabel, 0xffffffff, PFChan_Core_SESSION_ENDED);
  449. Map_OfSessionsByIp6_remove(i, &sm->ifaceMap);
  450. Allocator_free(sess->alloc);
  451. continue;
  452. }
  453. if (now - sess->pub.timeOfLastUsage > sm->pub.sessionTimeoutMilliseconds) {
  454. // This session is either only used by the pathfinder or it is nolonger used
  455. // let the pathfinder maintain it if it wants to, otherwise let it drop.
  456. //
  457. // This is a convenience for user tools to know that it's unmanaged.
  458. sess->pub.timeOfLastUsage = 0;
  459. } else if (now - sess->pub.lastSearchTime >= sm->pub.sessionSearchAfterMilliseconds) {
  460. // Session is not in idle state and requires a search
  461. debugSession0(sm->log, sess, "it's been a while, triggering search");
  462. triggerSearch(sm, sess->pub.caSession->herIp6, sess->pub.version);
  463. sess->pub.lastSearchTime = now;
  464. } else if (CryptoAuth_getState(sess->pub.caSession) < CryptoAuth_State_ESTABLISHED) {
  465. debugSession0(sm->log, sess, "triggering unsetupSession");
  466. unsetupSession(sm, sess);
  467. }
  468. }
  469. }
  470. static void periodically(void* vSessionManager)
  471. {
  472. struct SessionManager_pvt* sm = Identity_check((struct SessionManager_pvt*) vSessionManager);
  473. checkTimedOutSessions(sm);
  474. checkTimedOutBuffers(sm);
  475. }
  476. static void bufferPacket(struct SessionManager_pvt* sm, struct Message* msg)
  477. {
  478. Assert_true(msg->length >= (RouteHeader_SIZE + DataHeader_SIZE));
  479. struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
  480. // We should never be sending CJDHT messages without full version, key, path known.
  481. struct DataHeader* dataHeader = (struct DataHeader*) &header[1];
  482. Assert_true(DataHeader_getContentType(dataHeader) != ContentType_CJDHT);
  483. uint8_t ipStr[40];
  484. AddrTools_printIp(ipStr, header->ip6);
  485. int index = Map_BufferedMessages_indexForKey((struct Ip6*)header->ip6, &sm->bufMap);
  486. if (index > -1) {
  487. struct BufferedMessage* buffered = sm->bufMap.values[index];
  488. Map_BufferedMessages_remove(index, &sm->bufMap);
  489. Allocator_free(buffered->alloc);
  490. Log_debug(sm->log, "Buffering a packet to [%s] DROP replacing one in the buffer", ipStr);
  491. } else {
  492. Log_debug(sm->log, "Buffering a packet to [%s]", ipStr);
  493. }
  494. if ((int)sm->bufMap.count >= sm->pub.maxBufferedMessages) {
  495. checkTimedOutBuffers(sm);
  496. if ((int)sm->bufMap.count >= sm->pub.maxBufferedMessages) {
  497. Log_debug(sm->log, "DROP message needing lookup maxBufferedMessages ([%d]) is reached",
  498. sm->pub.maxBufferedMessages);
  499. return;
  500. }
  501. }
  502. struct Allocator* lookupAlloc = Allocator_child(sm->alloc);
  503. struct BufferedMessage* buffered =
  504. Allocator_calloc(lookupAlloc, sizeof(struct BufferedMessage), 1);
  505. buffered->msg = msg;
  506. buffered->alloc = lookupAlloc;
  507. buffered->timeSentMilliseconds = Time_currentTimeMilliseconds(sm->eventBase);
  508. Allocator_adopt(lookupAlloc, msg->alloc);
  509. Assert_true(Map_BufferedMessages_put((struct Ip6*)header->ip6, &buffered, &sm->bufMap) > -1);
  510. }
  511. static void needsLookup(struct SessionManager_pvt* sm, struct Message* msg)
  512. {
  513. struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
  514. bufferPacket(sm, msg);
  515. triggerSearch(sm, header->ip6, Endian_hostToBigEndian32(header->version_be));
  516. }
  517. static Iface_DEFUN readyToSend(struct Message* msg,
  518. struct SessionManager_pvt* sm,
  519. struct SessionManager_Session_pvt* sess)
  520. {
  521. struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
  522. Er_assert(Message_eshift(msg, -RouteHeader_SIZE));
  523. struct SwitchHeader* sh;
  524. CryptoAuth_resetIfTimeout(sess->pub.caSession);
  525. if (CryptoAuth_getState(sess->pub.caSession) < CryptoAuth_State_RECEIVED_KEY) {
  526. // Put the handle into the message so that it's authenticated.
  527. Er_assert(Message_epush32be(msg, sess->pub.receiveHandle));
  528. // Copy back the SwitchHeader so it is not clobbered.
  529. Er_assert(Message_eshift(msg, (CryptoHeader_SIZE + SwitchHeader_SIZE)));
  530. Bits_memcpy(msg->bytes, &header->sh, SwitchHeader_SIZE);
  531. sh = (struct SwitchHeader*) msg->bytes;
  532. Er_assert(Message_eshift(msg, -(CryptoHeader_SIZE + SwitchHeader_SIZE)));
  533. } else {
  534. sh = &header->sh;
  535. }
  536. // This pointer ceases to be useful.
  537. header = NULL;
  538. sess->pub.bytesOut += msg->length;
  539. Assert_true(!CryptoAuth_encrypt(sess->pub.caSession, msg));
  540. if (CryptoAuth_getState(sess->pub.caSession) >= CryptoAuth_State_RECEIVED_KEY) {
  541. if (0) { // Noisy
  542. debugHandlesAndLabel0(sm->log,
  543. sess,
  544. Endian_bigEndianToHost64(sh->label_be),
  545. "sending run message");
  546. }
  547. Er_assert(Message_epush32be(msg, sess->pub.sendHandle));
  548. } else {
  549. debugHandlesAndLabel0(sm->log,
  550. sess,
  551. Endian_bigEndianToHost64(sh->label_be),
  552. "sending start message");
  553. }
  554. // The SwitchHeader should have been moved to the correct location.
  555. Er_assert(Message_eshift(msg, SwitchHeader_SIZE));
  556. Assert_true((uint8_t*)sh == msg->bytes);
  557. if (!sh->label_be) {
  558. Bits_memset(sh, 0, SwitchHeader_SIZE);
  559. sh->label_be = Endian_hostToBigEndian64(sess->pub.sendSwitchLabel);
  560. SwitchHeader_setVersion(sh, SwitchHeader_CURRENT_VERSION);
  561. }
  562. return Iface_next(&sm->pub.switchIf, msg);
  563. }
  564. static Iface_DEFUN outgoingCtrlFrame(struct Message* msg, struct SessionManager_pvt* sm)
  565. {
  566. Assert_true(msg->length >= RouteHeader_SIZE);
  567. struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
  568. if (!Bits_isZero(header->publicKey, 32) || !Bits_isZero(header->ip6, 16)) {
  569. Log_debug(sm->log, "DROP Ctrl frame with non-zero destination key or IP");
  570. return NULL;
  571. }
  572. if (!(header->flags & RouteHeader_flags_CTRLMSG)) {
  573. Log_debug(sm->log, "DROP Ctrl frame w/o RouteHeader_flags_CTRLMSG flag");
  574. return NULL;
  575. }
  576. struct SwitchHeader sh;
  577. Bits_memcpy(&sh, &header->sh, SwitchHeader_SIZE);
  578. Er_assert(Message_epop(msg, NULL, RouteHeader_SIZE));
  579. Er_assert(Message_epush32be(msg, 0xffffffff));
  580. Er_assert(Message_epush(msg, &sh, SwitchHeader_SIZE));
  581. return Iface_next(&sm->pub.switchIf, msg);
  582. }
  583. static Iface_DEFUN incomingFromInsideIf(struct Message* msg, struct Iface* iface)
  584. {
  585. struct SessionManager_pvt* sm =
  586. Identity_containerOf(iface, struct SessionManager_pvt, pub.insideIf);
  587. Assert_true(msg->length >= RouteHeader_SIZE);
  588. struct RouteHeader* header = (struct RouteHeader*) msg->bytes;
  589. if (header->flags & RouteHeader_flags_CTRLMSG) {
  590. return outgoingCtrlFrame(msg, sm);
  591. }
  592. Assert_true(msg->length >= RouteHeader_SIZE + DataHeader_SIZE);
  593. struct DataHeader* dataHeader = (struct DataHeader*) &header[1];
  594. struct SessionManager_Session_pvt* sess = sessionForIp6(header->ip6, sm);
  595. if (!sess) {
  596. if (!Bits_isZero(header->publicKey, 32) && header->version_be) {
  597. sess = getSession(sm,
  598. header->ip6,
  599. header->publicKey,
  600. Endian_bigEndianToHost32(header->version_be),
  601. Endian_bigEndianToHost64(header->sh.label_be),
  602. Metric_SM_SEND);
  603. } else {
  604. needsLookup(sm, msg);
  605. return NULL;
  606. }
  607. }
  608. if (!(header->flags & RouteHeader_flags_PATHFINDER)) {
  609. // It's real life user traffic, lets tag the time of last use
  610. sess->pub.timeOfLastUsage = Time_currentTimeMilliseconds(sm->eventBase);
  611. }
  612. if (header->version_be) { sess->pub.version = Endian_bigEndianToHost32(header->version_be); }
  613. if (!sess->pub.version) {
  614. needsLookup(sm, msg);
  615. return NULL;
  616. }
  617. if (header->sh.label_be) {
  618. // fallthrough
  619. } else if (sess->pub.sendSwitchLabel) {
  620. Bits_memset(&header->sh, 0, SwitchHeader_SIZE);
  621. header->sh.label_be = Endian_hostToBigEndian64(sess->pub.sendSwitchLabel);
  622. SwitchHeader_setVersion(&header->sh, SwitchHeader_CURRENT_VERSION);
  623. } else {
  624. needsLookup(sm, msg);
  625. return NULL;
  626. }
  627. // Forward secrecy, only send dht messages until the session is setup.
  628. CryptoAuth_resetIfTimeout(sess->pub.caSession);
  629. if (CryptoAuth_getState(sess->pub.caSession) < CryptoAuth_State_RECEIVED_KEY) {
  630. if (DataHeader_getContentType(dataHeader) == ContentType_CJDHT) {
  631. if (sess->pub.timeOfLastUsage) {
  632. // Any time any message of any kind is sent down a link that is
  633. // currently in use, keep firing off unsetupSession
  634. debugSession0(sm->log, sess, "CJDHT traffic on link in use, unsetupSession");
  635. unsetupSession(sm, sess);
  636. }
  637. } else {
  638. debugSession0(sm->log, sess, "user traffic, unsetupSession");
  639. bufferPacket(sm, msg);
  640. unsetupSession(sm, sess);
  641. return NULL;
  642. }
  643. }
  644. return readyToSend(msg, sm, sess);
  645. }
  646. static Iface_DEFUN sessions(struct SessionManager_pvt* sm,
  647. uint32_t sourcePf,
  648. struct Allocator* tempAlloc)
  649. {
  650. for (int i = 0; i < (int)sm->ifaceMap.count; i++) {
  651. struct SessionManager_Session_pvt* sess = sm->ifaceMap.values[i];
  652. sendSession(sess, sess->pub.sendSwitchLabel, sourcePf, PFChan_Core_SESSION);
  653. }
  654. return NULL;
  655. }
  656. static Iface_DEFUN incomingFromEventIf(struct Message* msg, struct Iface* iface)
  657. {
  658. struct SessionManager_pvt* sm = Identity_containerOf(iface, struct SessionManager_pvt, eventIf);
  659. enum PFChan_Pathfinder ev = Er_assert(Message_epop32be(msg));
  660. uint32_t sourcePf = Er_assert(Message_epop32be(msg));
  661. if (ev == PFChan_Pathfinder_SESSIONS) {
  662. Assert_true(!msg->length);
  663. return sessions(sm, sourcePf, msg->alloc);
  664. }
  665. Assert_true(ev == PFChan_Pathfinder_NODE);
  666. struct PFChan_Node node;
  667. Er_assert(Message_epop(msg, &node, PFChan_Node_SIZE));
  668. Assert_true(!msg->length);
  669. int index = Map_BufferedMessages_indexForKey((struct Ip6*)node.ip6, &sm->bufMap);
  670. struct SessionManager_Session_pvt* sess = sessionForIp6(node.ip6, sm);
  671. if (!sess) {
  672. // Node we don't care about.
  673. if (index == -1) { return NULL; }
  674. // Broken path to a node we don't have a session for...
  675. if (node.metric_be == Metric_DEAD_LINK) { return NULL; }
  676. }
  677. sess = getSession(sm,
  678. node.ip6,
  679. node.publicKey,
  680. Endian_bigEndianToHost32(node.version_be),
  681. Endian_bigEndianToHost64(node.path_be),
  682. Endian_bigEndianToHost32(node.metric_be));
  683. // Send what's on the buffer...
  684. if (index > -1 && CryptoAuth_getState(sess->pub.caSession) >= CryptoAuth_State_RECEIVED_KEY) {
  685. struct BufferedMessage* bm = sm->bufMap.values[index];
  686. Iface_CALL(readyToSend, bm->msg, sm, sess);
  687. Map_BufferedMessages_remove(index, &sm->bufMap);
  688. Allocator_free(bm->alloc);
  689. }
  690. return NULL;
  691. }
  692. struct SessionManager* SessionManager_new(struct Allocator* allocator,
  693. struct EventBase* eventBase,
  694. struct CryptoAuth* cryptoAuth,
  695. struct Random* rand,
  696. struct Log* log,
  697. struct EventEmitter* ee)
  698. {
  699. struct Allocator* alloc = Allocator_child(allocator);
  700. struct SessionManager_pvt* sm = Allocator_calloc(alloc, sizeof(struct SessionManager_pvt), 1);
  701. sm->alloc = alloc;
  702. sm->pub.switchIf.send = incomingFromSwitchIf;
  703. sm->pub.insideIf.send = incomingFromInsideIf;
  704. sm->bufMap.allocator = alloc;
  705. sm->ifaceMap.allocator = alloc;
  706. sm->log = log;
  707. sm->cryptoAuth = cryptoAuth;
  708. sm->eventBase = eventBase;
  709. sm->pub.sessionTimeoutMilliseconds = SessionManager_SESSION_TIMEOUT_MILLISECONDS_DEFAULT;
  710. sm->pub.maxBufferedMessages = SessionManager_MAX_BUFFERED_MESSAGES_DEFAULT;
  711. sm->pub.sessionSearchAfterMilliseconds =
  712. SessionManager_SESSION_SEARCH_AFTER_MILLISECONDS_DEFAULT;
  713. sm->eventIf.send = incomingFromEventIf;
  714. EventEmitter_regCore(ee, &sm->eventIf, PFChan_Pathfinder_NODE);
  715. EventEmitter_regCore(ee, &sm->eventIf, PFChan_Pathfinder_SESSIONS);
  716. sm->firstHandle =
  717. (Random_uint32(rand) % (MAX_FIRST_HANDLE - MIN_FIRST_HANDLE)) + MIN_FIRST_HANDLE;
  718. Timeout_setInterval(periodically, sm, 1000, eventBase, alloc);
  719. Identity_set(sm);
  720. return &sm->pub;
  721. }