subnet rfc
This commit is contained in:
parent
19711f2153
commit
bd8a817484
2 changed files with 594 additions and 11 deletions
|
@ -142,6 +142,328 @@ export default {
|
|||
return 'Unknown';
|
||||
}
|
||||
|
||||
function getRFCNetworkInfo(ip, cidr) {
|
||||
const ipLong = ipToLong(ip);
|
||||
const parts = ip.split('.');
|
||||
const firstOctet = parseInt(parts[0]);
|
||||
const secondOctet = parseInt(parts[1]);
|
||||
|
||||
// Check for specific RFC-defined ranges
|
||||
if (firstOctet === 0) {
|
||||
return {
|
||||
type: 'Current Network',
|
||||
description: 'RFC 1122: "This host on this network" - used only as source address',
|
||||
rfc: 'RFC 1122',
|
||||
cidr: '0.0.0.0/8'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 10) {
|
||||
return {
|
||||
type: 'Private Network',
|
||||
description: 'RFC 1918: Private IP address range for Class A networks',
|
||||
rfc: 'RFC 1918',
|
||||
cidr: '10.0.0.0/8'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 127) {
|
||||
return {
|
||||
type: 'Loopback',
|
||||
description: 'RFC 1122: Loopback addresses - packets sent to this address are processed locally',
|
||||
rfc: 'RFC 1122',
|
||||
cidr: '127.0.0.0/8'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 169 && secondOctet === 254) {
|
||||
return {
|
||||
type: 'Link-Local',
|
||||
description: 'RFC 3927: Automatic Private IP Addressing (APIPA) - used when DHCP fails',
|
||||
rfc: 'RFC 3927',
|
||||
cidr: '169.254.0.0/16'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 172 && secondOctet >= 16 && secondOctet <= 31) {
|
||||
return {
|
||||
type: 'Private Network',
|
||||
description: 'RFC 1918: Private IP address range for Class B networks',
|
||||
rfc: 'RFC 1918',
|
||||
cidr: '172.16.0.0/12'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 192 && secondOctet === 168) {
|
||||
return {
|
||||
type: 'Private Network',
|
||||
description: 'RFC 1918: Private IP address range for Class C networks',
|
||||
rfc: 'RFC 1918',
|
||||
cidr: '192.168.0.0/16'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 192 && secondOctet === 0 && parseInt(parts[2]) === 0) {
|
||||
return {
|
||||
type: 'IETF Protocol Assignments',
|
||||
description: 'RFC 5736: Reserved for IETF protocol assignments',
|
||||
rfc: 'RFC 5736',
|
||||
cidr: '192.0.0.0/24'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 192 && secondOctet === 0 && parseInt(parts[2]) === 2) {
|
||||
return {
|
||||
type: 'Test-Net',
|
||||
description: 'RFC 5737: Documentation and example code (TEST-NET-1)',
|
||||
rfc: 'RFC 5737',
|
||||
cidr: '192.0.2.0/24'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 192 && secondOctet === 88 && parseInt(parts[2]) === 99) {
|
||||
return {
|
||||
type: '6to4 Relay',
|
||||
description: 'RFC 3068: IPv6 to IPv4 relay anycast addresses',
|
||||
rfc: 'RFC 3068',
|
||||
cidr: '192.88.99.0/24'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 198 && secondOctet === 18) {
|
||||
return {
|
||||
type: 'Benchmark Testing',
|
||||
description: 'RFC 2544: Network interconnect device benchmark testing',
|
||||
rfc: 'RFC 2544',
|
||||
cidr: '198.18.0.0/15'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 198 && secondOctet === 51 && parseInt(parts[2]) === 100) {
|
||||
return {
|
||||
type: 'Test-Net',
|
||||
description: 'RFC 5737: Documentation and example code (TEST-NET-2)',
|
||||
rfc: 'RFC 5737',
|
||||
cidr: '198.51.100.0/24'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 203 && secondOctet === 0 && parseInt(parts[2]) === 113) {
|
||||
return {
|
||||
type: 'Test-Net',
|
||||
description: 'RFC 5737: Documentation and example code (TEST-NET-3)',
|
||||
rfc: 'RFC 5737',
|
||||
cidr: '203.0.113.0/24'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet === 100 && secondOctet >= 64 && secondOctet <= 127) {
|
||||
return {
|
||||
type: 'CGNAT',
|
||||
description: 'RFC 6598: Carrier-Grade NAT (CGN) shared address space',
|
||||
rfc: 'RFC 6598',
|
||||
cidr: '100.64.0.0/10'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet >= 224 && firstOctet <= 239) {
|
||||
return {
|
||||
type: 'Multicast',
|
||||
description: 'RFC 1112: Multicast addresses - used for one-to-many communication',
|
||||
rfc: 'RFC 1112',
|
||||
cidr: '224.0.0.0/4'
|
||||
};
|
||||
}
|
||||
|
||||
if (firstOctet >= 240 && firstOctet <= 255) {
|
||||
return {
|
||||
type: 'Reserved',
|
||||
description: 'RFC 1112: Reserved for future use (formerly Class E)',
|
||||
rfc: 'RFC 1112',
|
||||
cidr: '240.0.0.0/4'
|
||||
};
|
||||
}
|
||||
|
||||
if (ipLong === 0xFFFFFFFF) {
|
||||
return {
|
||||
type: 'Broadcast',
|
||||
description: 'RFC 919: Limited broadcast address - reaches all hosts on the local network',
|
||||
rfc: 'RFC 919'
|
||||
};
|
||||
}
|
||||
|
||||
// Check for other broadcast addresses based on CIDR
|
||||
if (cidr < 32) {
|
||||
const networkLong = (ipLong & ((0xFFFFFFFF << (32 - cidr)) >>> 0)) >>> 0;
|
||||
const broadcastLong = (networkLong | (~((0xFFFFFFFF << (32 - cidr)) >>> 0)) >>> 0) >>> 0;
|
||||
if (ipLong === broadcastLong) {
|
||||
return {
|
||||
type: 'Network Broadcast',
|
||||
description: `Broadcast address for /${cidr} network - reaches all hosts in this subnet`,
|
||||
rfc: 'RFC 919'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Default case - public IP
|
||||
return {
|
||||
type: 'Public IP',
|
||||
description: 'Globally routable IP address on the Internet',
|
||||
rfc: null
|
||||
};
|
||||
}
|
||||
|
||||
function getIPv6NetworkInfo(ipv6, cidr) {
|
||||
const expanded = expandIPv6(ipv6);
|
||||
const parts = expanded.split(':');
|
||||
|
||||
// Convert to BigInt for comparison
|
||||
let ipv6Long = 0n;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const part = parseInt(parts[i], 16);
|
||||
ipv6Long = (ipv6Long << 16n) + BigInt(part);
|
||||
}
|
||||
|
||||
// Check for specific IPv6 reserved ranges
|
||||
|
||||
// ::/128 - Unspecified address
|
||||
if (ipv6Long === 0n) {
|
||||
return {
|
||||
type: 'Unspecified',
|
||||
description: 'RFC 4291: Unspecified address - used only as source address',
|
||||
rfc: 'RFC 4291',
|
||||
cidr: '::/128'
|
||||
};
|
||||
}
|
||||
|
||||
// ::1/128 - Loopback
|
||||
if (ipv6Long === 1n) {
|
||||
return {
|
||||
type: 'Loopback',
|
||||
description: 'RFC 4291: Loopback address - equivalent to IPv4 127.0.0.1',
|
||||
rfc: 'RFC 4291',
|
||||
cidr: '::1/128'
|
||||
};
|
||||
}
|
||||
|
||||
// 2000::/3 - Global Unicast (public IPv6)
|
||||
if ((ipv6Long >> 125n) === 4n) { // First 3 bits are 001
|
||||
return {
|
||||
type: 'Global Unicast',
|
||||
description: 'RFC 4291: Globally routable IPv6 addresses (public Internet)',
|
||||
rfc: 'RFC 4291',
|
||||
cidr: '2000::/3'
|
||||
};
|
||||
}
|
||||
|
||||
// fc00::/7 - Unique Local Address (ULA)
|
||||
if ((ipv6Long >> 121n) === 0x7Dn) { // First 7 bits are 1111110
|
||||
return {
|
||||
type: 'Unique Local Address',
|
||||
description: 'RFC 4193: Private IPv6 addresses (equivalent to IPv4 private ranges)',
|
||||
rfc: 'RFC 4193',
|
||||
cidr: 'fc00::/7'
|
||||
};
|
||||
}
|
||||
|
||||
// fe80::/10 - Link-Local
|
||||
if ((ipv6Long >> 118n) === 0xFE80n >> 6n) { // First 10 bits are 1111111010
|
||||
return {
|
||||
type: 'Link-Local',
|
||||
description: 'RFC 4291: Link-local addresses - valid only on the local network segment',
|
||||
rfc: 'RFC 4291',
|
||||
cidr: 'fe80::/10'
|
||||
};
|
||||
}
|
||||
|
||||
// ff00::/8 - Multicast
|
||||
if ((ipv6Long >> 120n) === 0xFFn) { // First 8 bits are 11111111
|
||||
return {
|
||||
type: 'Multicast',
|
||||
description: 'RFC 4291: IPv6 multicast addresses - used for one-to-many communication',
|
||||
rfc: 'RFC 4291',
|
||||
cidr: 'ff00::/8'
|
||||
};
|
||||
}
|
||||
|
||||
// 2001:db8::/32 - Documentation
|
||||
if ((ipv6Long >> 96n) === 0x20010DB8n) {
|
||||
return {
|
||||
type: 'Documentation',
|
||||
description: 'RFC 3849: Reserved for documentation and example code',
|
||||
rfc: 'RFC 3849',
|
||||
cidr: '2001:db8::/32'
|
||||
};
|
||||
}
|
||||
|
||||
// 2001::/32 - Teredo
|
||||
if ((ipv6Long >> 96n) === 0x20010000n) {
|
||||
return {
|
||||
type: 'Teredo',
|
||||
description: 'RFC 4380: Teredo tunneling - IPv6 over UDP over IPv4',
|
||||
rfc: 'RFC 4380',
|
||||
cidr: '2001::/32'
|
||||
};
|
||||
}
|
||||
|
||||
// 2002::/16 - 6to4
|
||||
if ((ipv6Long >> 112n) === 0x2002n) {
|
||||
return {
|
||||
type: '6to4',
|
||||
description: 'RFC 3056: 6to4 tunneling - automatic IPv6 over IPv4 tunneling',
|
||||
rfc: 'RFC 3056',
|
||||
cidr: '2002::/16'
|
||||
};
|
||||
}
|
||||
|
||||
// 64:ff9b::/96 - IPv4-IPv6 Translation
|
||||
if ((ipv6Long >> 96n) === 0x64FF9B000000000000000000n) {
|
||||
return {
|
||||
type: 'IPv4-IPv6 Translation',
|
||||
description: 'RFC 6052: Well-known prefix for IPv4-IPv6 translation',
|
||||
rfc: 'RFC 6052',
|
||||
cidr: '64:ff9b::/96'
|
||||
};
|
||||
}
|
||||
|
||||
// 100::/64 - Discard-Only
|
||||
if ((ipv6Long >> 64n) === 0x100000000000000n) {
|
||||
return {
|
||||
type: 'Discard-Only',
|
||||
description: 'RFC 6666: Discard-only address block - packets are discarded',
|
||||
rfc: 'RFC 6666',
|
||||
cidr: '100::/64'
|
||||
};
|
||||
}
|
||||
|
||||
// ::ffff:0:0/96 - IPv4-mapped IPv6
|
||||
if ((ipv6Long >> 96n) === 0xFFFF00000000n) {
|
||||
return {
|
||||
type: 'IPv4-mapped IPv6',
|
||||
description: 'RFC 4291: IPv4 addresses mapped to IPv6 format',
|
||||
rfc: 'RFC 4291',
|
||||
cidr: '::ffff:0:0/96'
|
||||
};
|
||||
}
|
||||
|
||||
// ::/96 - IPv4-compatible IPv6 (deprecated)
|
||||
if ((ipv6Long >> 96n) === 0n && (ipv6Long & 0xFFFFFFFF00000000n) === 0n) {
|
||||
return {
|
||||
type: 'IPv4-compatible IPv6',
|
||||
description: 'RFC 4291: IPv4-compatible IPv6 addresses (deprecated)',
|
||||
rfc: 'RFC 4291',
|
||||
cidr: '::/96'
|
||||
};
|
||||
}
|
||||
|
||||
// Default case - other reserved or unknown
|
||||
return {
|
||||
type: 'Reserved/Unknown',
|
||||
description: 'Reserved or unassigned IPv6 address range',
|
||||
rfc: null
|
||||
};
|
||||
}
|
||||
|
||||
function ipToLong(ip) {
|
||||
return ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet), 0) >>> 0;
|
||||
}
|
||||
|
@ -375,19 +697,52 @@ export default {
|
|||
const networkSize = Math.pow(2, 32 - cidr);
|
||||
const baseLong = ipToLong(baseIP);
|
||||
|
||||
// Calculate the base network for the IP (up to /16 level)
|
||||
// For example: 192.168.1.0 -> 192.168.0.0 (base /16 network)
|
||||
const baseNetworkLong = baseLong & ((0xFFFFFFFF << (32 - 16)) >>> 0);
|
||||
const networkLong = baseNetworkLong;
|
||||
// Calculate the base network for the IP based on the CIDR
|
||||
// For larger subnets (CIDR < 16), we need to find the appropriate base network
|
||||
let baseNetworkLong;
|
||||
let maxNetworks;
|
||||
|
||||
// Show up to 64 networks
|
||||
const count = Math.min(64, Math.floor(65536 / networkSize));
|
||||
if (cidr <= 8) {
|
||||
// For /8 and larger, use /8 as the base (Class A)
|
||||
baseNetworkLong = baseLong & ((0xFFFFFFFF << (32 - 8)) >>> 0);
|
||||
maxNetworks = Math.min(64, Math.floor(16777216 / networkSize)); // 2^24 / networkSize
|
||||
} else if (cidr <= 16) {
|
||||
// For /9 to /16, use /16 as the base (Class B)
|
||||
baseNetworkLong = baseLong & ((0xFFFFFFFF << (32 - 16)) >>> 0);
|
||||
maxNetworks = Math.min(64, Math.floor(65536 / networkSize)); // 2^16 / networkSize
|
||||
} else {
|
||||
// For /17 and smaller, use the actual network as base
|
||||
baseNetworkLong = baseLong & ((0xFFFFFFFF << (32 - cidr)) >>> 0);
|
||||
maxNetworks = Math.min(64, Math.floor(65536 / networkSize));
|
||||
}
|
||||
|
||||
// Show up to 64 networks, but limit based on what makes sense
|
||||
const count = Math.min(maxNetworks, 64);
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const networkAddr = networkLong + (i * networkSize);
|
||||
const networkAddr = baseNetworkLong + (i * networkSize);
|
||||
const broadcastAddr = networkAddr + networkSize - 1;
|
||||
const firstHost = networkAddr + 1;
|
||||
const lastHost = broadcastAddr - 1;
|
||||
|
||||
// Handle edge cases for host calculations
|
||||
let firstHost, lastHost;
|
||||
|
||||
if (cidr === 32) {
|
||||
// /32 - single host, no usable hosts
|
||||
firstHost = networkAddr;
|
||||
lastHost = networkAddr;
|
||||
} else if (cidr === 31) {
|
||||
// /31 - point-to-point, no usable hosts
|
||||
firstHost = networkAddr;
|
||||
lastHost = broadcastAddr;
|
||||
} else if (cidr === 30) {
|
||||
// /30 - 4 total hosts, 2 usable
|
||||
firstHost = networkAddr + 1;
|
||||
lastHost = broadcastAddr - 1;
|
||||
} else {
|
||||
// Normal case - calculate usable hosts
|
||||
firstHost = networkAddr + 1;
|
||||
lastHost = broadcastAddr - 1;
|
||||
}
|
||||
|
||||
networks.push({
|
||||
network: longToIp(networkAddr),
|
||||
|
@ -452,13 +807,27 @@ export default {
|
|||
lastHostLong = broadcastLong - 1;
|
||||
}
|
||||
|
||||
// Calculate total possible networks
|
||||
// Calculate total possible networks based on CIDR
|
||||
const networkSize = Math.pow(2, 32 - calculatedCidr);
|
||||
const totalPossibleNetworks = Math.floor(65536 / networkSize);
|
||||
let totalPossibleNetworks;
|
||||
|
||||
if (calculatedCidr <= 8) {
|
||||
// For /8 and larger, calculate based on Class A space
|
||||
totalPossibleNetworks = Math.floor(16777216 / networkSize); // 2^24 / networkSize
|
||||
} else if (calculatedCidr <= 16) {
|
||||
// For /9 to /16, calculate based on Class B space
|
||||
totalPossibleNetworks = Math.floor(65536 / networkSize); // 2^16 / networkSize
|
||||
} else {
|
||||
// For /17 and smaller, use the standard calculation
|
||||
totalPossibleNetworks = Math.floor(65536 / networkSize);
|
||||
}
|
||||
|
||||
// Generate available networks table
|
||||
const availableNetworks = generateAvailableNetworks(ipAddress, calculatedCidr);
|
||||
|
||||
// Get RFC network information
|
||||
const rfcInfo = getRFCNetworkInfo(ipAddress, calculatedCidr);
|
||||
|
||||
out.innerHTML = `
|
||||
<div style="font-size: 24px; font-weight: 700; color: var(--accent); margin-bottom: 15px;">
|
||||
IPv4 Subnet Information
|
||||
|
@ -505,6 +874,22 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background: var(--border); padding: 15px; border-radius: 8px; margin-top: 15px;">
|
||||
<h4 style="color: var(--accent); margin-bottom: 10px;">Network Type Information</h4>
|
||||
<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>Network Type:</strong> ${rfcInfo.type}
|
||||
</div>
|
||||
<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>Description:</strong> ${rfcInfo.description}
|
||||
</div>
|
||||
${rfcInfo.cidr ? `<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>RFC Range:</strong> ${rfcInfo.cidr}
|
||||
</div>` : ''}
|
||||
${rfcInfo.rfc ? `<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>RFC Reference:</strong> ${rfcInfo.rfc}
|
||||
</div>` : ''}
|
||||
</div>
|
||||
|
||||
<div style="background: var(--border); padding: 15px; border-radius: 8px; margin-top: 15px;">
|
||||
<h4 style="color: var(--accent); margin-bottom: 10px;">Binary Representation</h4>
|
||||
<div style="font-family: monospace; font-size: 14px; color: var(--text); margin-bottom: 5px;">
|
||||
|
@ -617,6 +1002,9 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
// Get IPv6 network information
|
||||
const ipv6NetworkInfo = getIPv6NetworkInfo(ipv6Address, ipv6Cidr);
|
||||
|
||||
// Format large numbers for display
|
||||
function formatBigInt(num) {
|
||||
if (num < BigInt(1e6)) {
|
||||
|
@ -688,6 +1076,22 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div style="background: var(--border); padding: 15px; border-radius: 8px; margin-top: 15px;">
|
||||
<h4 style="color: var(--accent); margin-bottom: 10px;">Network Type Information</h4>
|
||||
<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>Network Type:</strong> ${ipv6NetworkInfo.type}
|
||||
</div>
|
||||
<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>Description:</strong> ${ipv6NetworkInfo.description}
|
||||
</div>
|
||||
${ipv6NetworkInfo.cidr ? `<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>RFC Range:</strong> ${ipv6NetworkInfo.cidr}
|
||||
</div>` : ''}
|
||||
${ipv6NetworkInfo.rfc ? `<div style="color: var(--text); margin-bottom: 5px;">
|
||||
<strong>RFC Reference:</strong> ${ipv6NetworkInfo.rfc}
|
||||
</div>` : ''}
|
||||
</div>
|
||||
|
||||
<div style="background: var(--border); padding: 15px; border-radius: 8px; margin-top: 15px;">
|
||||
<h4 style="color: var(--accent); margin-bottom: 10px;">Available Networks</h4>
|
||||
<div style="overflow-x: auto;">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue