1
0

traceroute 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. #!/usr/bin/env node
  2. /* -*- Mode:js */
  3. /* vim: set expandtab ts=4 sw=4: */
  4. /*
  5. * You may redistribute this program and/or modify it under the terms of
  6. * the GNU General Public License as published by the Free Software Foundation,
  7. * either version 3 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. */
  17. var Cjdns = require('./lib/cjdnsadmin/cjdnsadmin');
  18. var nThen = require('nthen');
  19. var PubToIp6 = require('./lib/publicToIp6');
  20. var Dns = require('dns');
  21. var IP6_REGEX = new RegExp('^' + new Array(9).join(':[0-9a-f]{1,4}').substring(1) + '$');
  22. var LABEL_REGEX = new RegExp('^' + new Array(5).join('.[0-9a-f]{4}').substring(1) + '$');
  23. var ADDR_REGEX = new RegExp('^v[0-9]+' + new Array(5).join('\\.[0-9a-f]{4}') + '\\.[a-z0-9]{52}\\.k$');
  24. var validTarget = function (target) {
  25. if (IP6_REGEX.test(target)) { return true; }
  26. if (LABEL_REGEX.test(target)) { return true; }
  27. if (ADDR_REGEX.test(target)) { return true; }
  28. return false;
  29. };
  30. var nodeToIP6 = function (nodeDesc) {
  31. var key = nodeDesc.replace(/.*\.([^.]*\.k)$/, function (all, one) { return one; });
  32. return PubToIp6.convert(key);
  33. };
  34. var highBits = function (nodeDesc) {
  35. var ip6 = nodeToIP6(nodeDesc);
  36. return ip6.substring(20,29);
  37. }
  38. var tracePath = function (target, queryNode, cjdns, cb, doneCb) {
  39. var lastNode = queryNode;
  40. var again = function () {
  41. cjdns.RouterModule_nextHop(target, lastNode, function (err, ret) {
  42. if (err) { throw err; }
  43. ret.from = lastNode;
  44. ret.fromIP6 = nodeToIP6(lastNode);
  45. cb(ret);
  46. if (ret.error !== 'none' || !ret.nodes || !ret.nodes.length) {
  47. doneCb(false);
  48. return;
  49. }
  50. if (ret.fromIP6 === target || ret.from === ret.nodes[0]) {
  51. doneCb(true);
  52. return;
  53. }
  54. lastNode = ret.nodes[0];
  55. again();
  56. });
  57. };
  58. again();
  59. };
  60. var main = function (target) {
  61. var cjdns;
  62. var self;
  63. var lastRet;
  64. nThen(function (waitFor) {
  65. Cjdns.connectWithAdminInfo(waitFor(function (c) { cjdns = c; }));
  66. if (!validTarget(target)) {
  67. Dns.lookup(target, 6, waitFor(function (err, res) {
  68. if (err) { throw err; }
  69. console.log(target + ' has ip address ' + res);
  70. target = res;
  71. }));
  72. }
  73. }).nThen(function (waitFor) {
  74. cjdns.RouterModule_getPeers("0000.0000.0000.0001", waitFor(function (err, ret) {
  75. if (err) { throw err; }
  76. self = ret.peers[0];
  77. }));
  78. }).nThen(function (waitFor) {
  79. process.stdout.write(self + ' ' + highBits(self));
  80. tracePath(target, self, cjdns, function (ret) {
  81. lastRet = ret;
  82. process.stdout.write(' ' + ret.ms + 'ms\n');
  83. if (ret.nodes.length === 0) {
  84. console.log('cornered');
  85. } else if (ret.nodes[0] !== ret.from) {
  86. process.stdout.write(ret.nodes[0] + ' ' + highBits(ret.nodes[0]));
  87. }
  88. }, waitFor());
  89. }).nThen(function (waitFor) {
  90. if (!lastRet || lastRet.nodes[0] !== lastRet.from) { return; }
  91. console.log('success, trying reverse trace');
  92. process.stdout.write(lastRet.from);
  93. tracePath(nodeToIP6(self), lastRet.from, cjdns, function (ret) {
  94. lastRet = ret;
  95. process.stdout.write(' ' + ret.ms + 'ms\n');
  96. if (ret.result === 'timeout') {
  97. process.stdout.write('\n' + ret.from + ' ' + ret.result + '!');
  98. } else if (ret.nodes.length === 0) {
  99. console.log('cornered');
  100. } else if (ret.nodes[0] !== ret.from) {
  101. process.stdout.write(ret.nodes[0] + ' ' + highBits(ret.nodes[0]));
  102. }
  103. }, waitFor());
  104. }).nThen(function (waitFor) {
  105. console.log();
  106. cjdns.disconnect();
  107. });
  108. };
  109. main(process.argv[process.argv.length-1]);