ObjFW  Check-in [af9084b456]

Overview
Comment:Add support for IPv4s embedded into IPv6s
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: af9084b4569e4546a6592444f78720b136e15d6528236eccb59f74c974743643
User & Date: js on 2023-06-11 16:45:03
Other Links: manifest | tags
References
2023-06-11
16:50 Fixed ticket [6519b5a25e]: Support for addresses like ::ffff:127.0.0.1 in OFSocketAddressParseIPv6() plus 4 other changes artifact: fb8aed41ff user: js
Context
2023-06-11
19:58
+[OFSystemInfo networkInterfaces]: MAC on Linux check-in: ccf154b51a user: js tags: trunk
16:45
Add support for IPv4s embedded into IPv6s check-in: af9084b456 user: js tags: trunk
10:46
+[OFSystemInfo networkInterfaces]: Add HW address check-in: 1aeb540a82 user: js tags: trunk
Changes

Modified src/OFSocket.m from [788a494072] to [d7a63b18b9].

428
429
430
431
432
433
434




























435
436
437
438
439
440
441
	number = [component unsignedLongLongValueWithBase: 16];

	if (number > UINT16_MAX)
		@throw [OFInvalidFormatException exception];

	return (uint16_t)number;
}





























OFSocketAddress
OFSocketAddressParseIPv6(OFString *IPv6, uint16_t port)
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress ret;
	struct sockaddr_in6 *addrIn6 = &ret.sockaddr.in6;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
	number = [component unsignedLongLongValueWithBase: 16];

	if (number > UINT16_MAX)
		@throw [OFInvalidFormatException exception];

	return (uint16_t)number;
}

static OFString *
transformEmbeddedIPv4(OFString *IPv6)
{
	size_t lastColon = [IPv6
	    rangeOfString: @":"
		  options: OFStringSearchBackwards].location;
	OFString *IPv4;
	OFSocketAddress address;
	const struct sockaddr_in *addrIn;
	uint32_t addr;

	if (lastColon == OFNotFound)
		@throw [OFInvalidFormatException exception];

	IPv4 = [IPv6 substringWithRange:
	    OFMakeRange(lastColon + 1, IPv6.length - lastColon - 1)];
	IPv6 = [IPv6 substringWithRange: OFMakeRange(0, lastColon + 1)];

	address = OFSocketAddressParseIPv4(IPv4, 0);
	addrIn = &address.sockaddr.in;
	addr = OFFromBigEndian32(addrIn->sin_addr.s_addr);

	return [IPv6 stringByAppendingString:
	    [OFString stringWithFormat: @"%x%02x:%x%02x",
	    (addr & 0xFF000000) >> 24, (addr & 0x00FF0000) >> 16,
	    (addr & 0x0000FF00) >>  8, addr & 0x000000FF]];
}

OFSocketAddress
OFSocketAddressParseIPv6(OFString *IPv6, uint16_t port)
{
	void *pool = objc_autoreleasePoolPush();
	OFSocketAddress ret;
	struct sockaddr_in6 *addrIn6 = &ret.sockaddr.in6;
465
466
467
468
469
470
471



472
473
474
475
476
477
478
			    cStringWithEncoding: [OFLocale encoding]]);
#endif
		}

		if (addrIn6->sin6_scope_id == 0)
			@throw [OFInvalidArgumentException exception];
	}




	doubleColon = [IPv6 rangeOfString: @"::"].location;
	if (doubleColon != OFNotFound) {
		OFString *left = [IPv6 substringToIndex: doubleColon];
		OFString *right = [IPv6 substringFromIndex: doubleColon + 2];
		OFArray OF_GENERIC(OFString *) *leftComponents;
		OFArray OF_GENERIC(OFString *) *rightComponents;







>
>
>







493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
			    cStringWithEncoding: [OFLocale encoding]]);
#endif
		}

		if (addrIn6->sin6_scope_id == 0)
			@throw [OFInvalidArgumentException exception];
	}

	if ([IPv6 rangeOfString: @"."].location != OFNotFound)
		IPv6 = transformEmbeddedIPv4(IPv6);

	doubleColon = [IPv6 rangeOfString: @"::"].location;
	if (doubleColon != OFNotFound) {
		OFString *left = [IPv6 substringToIndex: doubleColon];
		OFString *right = [IPv6 substringFromIndex: doubleColon + 2];
		OFArray OF_GENERIC(OFString *) *leftComponents;
		OFArray OF_GENERIC(OFString *) *rightComponents;

Modified tests/OFSocketTests.m from [250609ea2a] to [4114d19b90].

117
118
119
120
121
122
123










124
125
126
127
128
129
130

	TEST(@"Parsing an IPv6 #6",
	    R(addr = OFSocketAddressParseIP(@"fd00::1%123", 1234)) &&
	    COMPARE_V6(addr, 0xFD00, 0, 0, 0, 0, 0, 0, 1) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234 &&
	    addr.sockaddr.in6.sin6_scope_id == 123)











	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #1", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1:::2", 1234))

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #2", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1: ::2", 1234))

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #3", OFInvalidFormatException,







>
>
>
>
>
>
>
>
>
>







117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

	TEST(@"Parsing an IPv6 #6",
	    R(addr = OFSocketAddressParseIP(@"fd00::1%123", 1234)) &&
	    COMPARE_V6(addr, 0xFD00, 0, 0, 0, 0, 0, 0, 1) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234 &&
	    addr.sockaddr.in6.sin6_scope_id == 123)

	TEST(@"Parsing an IPv6 #7",
	    R(addr = OFSocketAddressParseIP(@"::ffff:127.0.0.1", 1234)) &&
	    COMPARE_V6(addr, 0, 0, 0, 0, 0, 0xFFFF, 0x7F00, 1) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	TEST(@"Parsing an IPv6 #8",
	    R(addr = OFSocketAddressParseIP(@"64:ff9b::127.0.0.1", 1234)) &&
	    COMPARE_V6(addr, 0x64, 0xFF9B, 0, 0, 0, 0, 0x7F00, 1) &&
	    OFFromBigEndian16(addr.sockaddr.in6.sin6_port) == 1234)

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #1", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1:::2", 1234))

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #2", OFInvalidFormatException,
	    OFSocketAddressParseIP(@"1: ::2", 1234))

	EXPECT_EXCEPTION(@"Refusing invalid IPv6 #3", OFInvalidFormatException,