ParseIPv4Header.mjs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /**
  2. * @author n1474335 [n1474335@gmail.com]
  3. * @copyright Crown Copyright 2016
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation";
  7. import Utils from "../Utils";
  8. import OperationError from "../errors/OperationError";
  9. import {fromHex, toHex} from "../lib/Hex";
  10. import {ipv4ToStr, protocolLookup} from "../lib/IP";
  11. import TCPIPChecksum from "./TCPIPChecksum";
  12. /**
  13. * Parse IPv4 header operation
  14. */
  15. class ParseIPv4Header extends Operation {
  16. /**
  17. * ParseIPv4Header constructor
  18. */
  19. constructor() {
  20. super();
  21. this.name = "Parse IPv4 header";
  22. this.module = "JSBN";
  23. this.description = "Given an IPv4 header, this operations parses and displays each field in an easily readable format.";
  24. this.inputType = "string";
  25. this.outputType = "html";
  26. this.args = [
  27. {
  28. "name": "Input format",
  29. "type": "option",
  30. "value": ["Hex", "Raw"]
  31. }
  32. ];
  33. }
  34. /**
  35. * @param {string} input
  36. * @param {Object[]} args
  37. * @returns {html}
  38. */
  39. run(input, args) {
  40. const format = args[0];
  41. let output;
  42. if (format === "Hex") {
  43. input = fromHex(input);
  44. } else if (format === "Raw") {
  45. input = Utils.strToByteArray(input);
  46. } else {
  47. throw new OperationError("Unrecognised input format.");
  48. }
  49. let ihl = input[0] & 0x0f;
  50. const dscp = (input[1] >>> 2) & 0x3f,
  51. ecn = input[1] & 0x03,
  52. length = input[2] << 8 | input[3],
  53. identification = input[4] << 8 | input[5],
  54. flags = (input[6] >>> 5) & 0x07,
  55. fragOffset = (input[6] & 0x1f) << 8 | input[7],
  56. ttl = input[8],
  57. protocol = input[9],
  58. checksum = input[10] << 8 | input[11],
  59. srcIP = input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15],
  60. dstIP = input[16] << 24 | input[17] << 16 | input[18] << 8 | input[19],
  61. checksumHeader = input.slice(0, 10).concat([0, 0]).concat(input.slice(12, 20));
  62. let version = (input[0] >>> 4) & 0x0f,
  63. options = [];
  64. // Version
  65. if (version !== 4) {
  66. version = version + " (Error: for IPv4 headers, this should always be set to 4)";
  67. }
  68. // IHL
  69. if (ihl < 5) {
  70. ihl = ihl + " (Error: this should always be at least 5)";
  71. } else if (ihl > 5) {
  72. // sort out options...
  73. const optionsLen = ihl * 4 - 20;
  74. options = input.slice(20, optionsLen + 20);
  75. }
  76. // Protocol
  77. const protocolInfo = protocolLookup[protocol] || {keyword: "", protocol: ""};
  78. // Checksum
  79. const correctChecksum = (new TCPIPChecksum).run(checksumHeader),
  80. givenChecksum = Utils.hex(checksum);
  81. let checksumResult;
  82. if (correctChecksum === givenChecksum) {
  83. checksumResult = givenChecksum + " (correct)";
  84. } else {
  85. checksumResult = givenChecksum + " (incorrect, should be " + correctChecksum + ")";
  86. }
  87. output = `<table class='table table-hover table-sm table-bordered table-nonfluid'><tr><th>Field</th><th>Value</th></tr>
  88. <tr><td>Version</td><td>${version}</td></tr>
  89. <tr><td>Internet Header Length (IHL)</td><td>${ihl} (${ihl * 4} bytes)</td></tr>
  90. <tr><td>Differentiated Services Code Point (DSCP)</td><td>${dscp}</td></tr>
  91. <tr><td>Explicit Congestion Notification (ECN)</td><td>${ecn}</td></tr>
  92. <tr><td>Total length</td><td>${length} bytes
  93. IP header: ${ihl * 4} bytes
  94. Data: ${length - ihl * 4} bytes</td></tr>
  95. <tr><td>Identification</td><td>0x${Utils.hex(identification)} (${identification})</td></tr>
  96. <tr><td>Flags</td><td>0x${Utils.hex(flags, 2)}
  97. Reserved bit:${flags >> 2} (must be 0)
  98. Don't fragment:${flags >> 1 & 1}
  99. More fragments:${flags & 1}</td></tr>
  100. <tr><td>Fragment offset</td><td>${fragOffset}</td></tr>
  101. <tr><td>Time-To-Live</td><td>${ttl}</td></tr>
  102. <tr><td>Protocol</td><td>${protocol}, ${protocolInfo.protocol} (${protocolInfo.keyword})</td></tr>
  103. <tr><td>Header checksum</td><td>${checksumResult}</td></tr>
  104. <tr><td>Source IP address</td><td>${ipv4ToStr(srcIP)}</td></tr>
  105. <tr><td>Destination IP address</td><td>${ipv4ToStr(dstIP)}</td></tr>`;
  106. if (ihl > 5) {
  107. output += `<tr><td>Options</td><td>${toHex(options)}</td></tr>`;
  108. }
  109. return output + "</table>";
  110. }
  111. }
  112. export default ParseIPv4Header;