Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions lib/ipaddr.js
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,15 @@
// in line with RFC 5952 (see https://tools.ietf.org/html/rfc5952#section-4)
IPv6.prototype.toRFC5952String = function () {
const regex = /((^|:)(0(:|$)){2,})/g;
const string = this.toNormalizedString();
// The zone identifier (RFC 4007) is not part of the address; match
// against the address alone so a trailing zero run right before the
// "%" suffix still gets compressed (RFC 5952, 4.2.2).
let suffix = '';
if (this.zoneId) {
suffix = `%${this.zoneId}`;
}
const normalized = this.toNormalizedString();
const string = normalized.slice(0, normalized.length - suffix.length);
let bestMatchIndex = 0;
let bestMatchLength = -1;
let bestMatchGroups = -1;
Expand All @@ -793,10 +801,10 @@
}

if (bestMatchLength < 0) {
return string;
return string + suffix;
}

return `${string.substring(0, bestMatchIndex)}::${string.substring(bestMatchIndex + bestMatchLength)}`;
return `${string.substring(0, bestMatchIndex)}::${string.substring(bestMatchIndex + bestMatchLength)}${suffix}`;
};

// Returns the address in compact, human-readable format like
Expand Down
9 changes: 9 additions & 0 deletions test/ipaddr.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,15 @@ describe('ipaddr', () => {
);
})

it('compresses a trailing zero run when a zoneIndex is present', () => {
// The zone identifier (RFC 4007) is not part of the address and must
// not prevent zero-run compression at the end of it (RFC 5952, 4.2.2).
assert.equal(new ipaddr.IPv6([0xfe80, 0, 0, 0, 0, 0, 0, 0], 'eth0').toString(), 'fe80::%eth0');
assert.equal(new ipaddr.IPv6([0x2001, 0xdb8, 0, 0, 0, 0, 0, 0], 'eth0').toRFC5952String(), '2001:db8::%eth0');
assert.equal(ipaddr.parse('fe80::%eth0').toString(), 'fe80::%eth0');
assert.equal(ipaddr.parse('::%eth0').toString(), '::%eth0');
})

it('returns IPv6 zoneIndex for IPv4-mapped IPv6 addresses', () => {
let addr = ipaddr.parse('::ffff:192.168.1.1%eth0');
assert.equal(addr.toNormalizedString(), '0:0:0:0:0:ffff:c0a8:101%eth0');
Expand Down