> results in hardcoding protocol details in application code
Are you suggesting that this could have been implemented a different way? Example: IP could be negotiated to upgrade from v4 to v6? I am curious about your ideas. > results in hardcoding protocol details in application code
Are you suggesting that this could have been implemented a different way? Example: IP could be negotiated to upgrade from v4 to v6? I am curious about your ideas.Of course, code that operates on packets, in the TCP/IP stack of the OS would have still needed to be rewritten. But that is far less code than "every application that opens a socket".
Of course, this only applies to code that uses IPs only to open connections. There's lots of application code that does more things with IPs, such as parsing, displaying, validating etc. All of this code would still need to be rewritten to accept IPv6 addresses (and its much more complex string representations), that part is inevitable.
While the sockaddr struct allowed to to abstractly handle v4/v6 socket connections, there wasn’t a clean way to do all of that additional stuff and IP address logic leaked into all kinds of software where you wouldn’t first expect it.
Something as simple as a web app that needs to inspect proxy headers would even have it.
It also didn’t help that it became practice to explicitly not trust the addr resolution offered by the sockets API because it would do unexpected things like resolving something that looked like an integer to a uint32 and then a 4 byte V4 addr.
Resolve the A and AAAA records, and try to connect to them at the same time. The first successful connection wins (maaaaybe with a slight bias for IPv6).
This would have required an API that uses the host name and folds the DNS resolution and connection into one call. Instead, the BSD socket API remained at the "network assembly" level with the `sockaddr_in/sockaddr_in6` structures used for address information.
For the examples I am going to use the typical "HTTP to example.com" case.
Some OSI-focused stacks provided high level abstraction that gave you a socket already set for listening or connected to another service, based on combination of "host name", "service name", and "service type".
You'd use something like
connect("example.com", "http", SVC_STREAM_GRACEFUL_CLOSE) // using OSI-like name for the kind of service TCP provides
and as far as application is concerned, it does not need to know if it's ipv4, ipv6, X.25, or a direct serial connection (OSI concept of separating "service" from "protocol" is really a great idea that got lost)Similar approach was done in Plan 9 (and thus everyone who uses Go is going to see something similar) with the dial API:
dial("example.com!http",0,0,0)
As part of IPv6 effort an attempt at providing something similar with BSD Sockets was made, namely getaddrinfo which gives back information to be fed to socket/bind/connect calls - but for a long time people still learnt from old material which had them manually fill in socket parameters without GAI so adoption was slowed down.It isn't about upgrading one protocol to another but about having the operating system abstract away the different protocols from the application.