Inconsistency and poor documentation

I was doing some further work on my Firefox extension SixOrNot last night, trying to improve the behavior and performance of the ctypes DNS resolution component. This uses JS-ctypes to access the native functionality of the underlying OS. Because of this it exposes me to the wonderful world of OS-specific network programming.

I’ve found some lovely inconsistencies which are made much worse by the poor documentation available. The worst offenders so far have been Microsoft and Apple.

Microsoft

On Windows there is support for the posix method getaddrinfo(), this is used to populate a linked list of addrinfo structures which can contain sockaddr structures (which themselves contain either IPv4 or IPv6 addresses – which is what I am after).

getaddrinfo() takes a hostname to lookup, a set of hints (which is an addrinfo struct defining the kinds of addresses you want to get back) and a pointer to the first addrinfo item of your output linked list (which it then populates). After you’re done reading the linked list you call freeaddrinfo() to free the dynamically allocated memory.

Calling this method on different platforms with null for the hints field has differing behavior when it comes to resolution of IPv6 addresses from DNS records. Below is a brief matrix.

Windows XP/Server 2003 – v4 and v6 returned always

Windows Vista/7 – v6 only when a local adapter has a global v6 address

OSX – v4 and v6 returned always

Linux (Ubuntu Natty) – v6 only when a local adapter has a global v6 address

There is a flag which enforces the behavior on Linux/Vista/Win7, AI_ADDRCONFIG, this is explained in the Microsoft documentation thusly:

http://msdn.microsoft.com/en-us/library/ms738520(v=vs.85).aspx

If the AI_ADDRCONFIG bit is set, getaddrinfo will resolve only if a global address is configured. If AI_ADDRCONFIG flag is specified, IPv4 addresses shall be returned only if an IPv4 address is configured on the local system, and IPv6 addresses shall be returned only if an IPv6 address is configured on the local system. The IPv4 or IPv6 loopback address is not considered a valid global address.

The AI_ADDRCONFIG flag is defined on the Windows SDK for Windows Vista and later. The AI_ADDRCONFIG flag is supported on Windows Vista and later.

What they don’t tell you (and this is critical!) is that AI_ADDRCONFIG is on by default in Vista/Win7 whether you set the flag or not. I only found this out by chance from reading the comments in the code of the Chromium project on this page:

http://src.chromium.org/svn/trunk/src/net/base/host_resolver_proc.cc

  // DO NOT USE AI_ADDRCONFIG ON WINDOWS.

//
// The following comment in is the best documentation I found
// on AI_ADDRCONFIG for Windows:
// Flags used in "hints" argument to getaddrinfo()
// - AI_ADDRCONFIG is supported starting with Vista
// - default is AI_ADDRCONFIG ON whether the flag is set or not
// because the performance penalty in not having ADDRCONFIG in
// the multi-protocol stack environment is severe;
// this defaulting may be disabled by specifying the AI_ALL flag,
// in that case AI_ADDRCONFIG must be EXPLICITLY specified to
// enable ADDRCONFIG behavior
//
// Not only is AI_ADDRCONFIG unnecessary, but it can be harmful. If the
// computer is not connected to a network, AI_ADDRCONFIG causes getaddrinfo
// to fail with WSANO_DATA (11004) for "localhost", probably because of the
// following note on AI_ADDRCONFIG in the MSDN getaddrinfo page:
// The IPv4 or IPv6 loopback address is not considered a valid global
// address.
// See http://crbug.com/5234.

The AI_ALL flag is defined in the Microsoft documentation thusly:

http://msdn.microsoft.com/en-us/library/ms738520(v=vs.85).aspx

If the AI_ALL bit is set, a request is made for IPv6 addresses and IPv4 addressses with AI_V4MAPPED.

The AI_ALL flag is defined on the Windows SDK for Windows Vista and later. The AI_ALL flag is supported on Windows Vista and later.

This is perfectly true, but it misses the key bit of information that if you want to override the default AI_ADDRCONFIG behavior you must use AI_ALL. Additionally it’s kind of misleading in that it hasn’t got a lot to do with the AI_V4MAPPED flag (and if you specify only AI_ALL you’ll get back normal v4 addresses – i.e. not mapped to IPv6 addresses…)

The same is true on Linux however their documentation actually specifies what the default flags are:

http://www.kernel.org/doc/man-pages/online/pages/man3/getaddrinfo.3.html

All the other fields in the structure pointed to by hints must contain either

0 or a null pointer, as appropriate. Specifying hints as NULL is equivalent

to setting ai_socktype and ai_protocol to 0; ai_family to AF_UNSPEC; and

ai_flags to (AI_V4MAPPED | AI_ADDRCONFIG).

Apple

This is a minor point but their developer documentation lists the fields of the addrinfo struct on this page incorrectly:

http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/getaddrinfo.3.html

The ai_addr and ai_canonname fields are reversed compared to what they actually are in netdb.h, this is actually slightly bizarre to me, why would they change two fields of such a basic posix networking structure around? And then mis-document them?

Still, after all that I have a better understanding of at least one cross-platform issue, and my extension works perfectly. Just really frustrating that I wasted so much time because a few lines of documentation were missing/misleading/inaccurate.

Advertisements

Connecting to SQL Server Embedded Edition

Quick note, you can connect to the SQL Server Embedded edition instance using this connection string:

\\.\pipe\mssql$microsoft##ssee\sql\query

Useful if you need to change the backup model for internal system databases using this provider…

SQL 2008 R2 SP1 – Unattended/command line install

This was a pain to get right, thanks Microsoft for the comprehensive documentation you provide on this kind of thing(!)

The contents of the .exe for SP1 can be extracted using WinZip/7Zip. They contain a setup.exe, this takes the following command line flags:

Microsoft (R) SQL Server 2008 R2 Setup 10.50.2500.00

Copyright (c) Microsoft Corporation. All rights reserved.

Usage:
setup.exe /[option]={value} /[option]={value} ...

Options:
ACTION Specifies a Setup work flow, like INSTALL,
UNINSTALL, or UPGRADE. This is a required
parameter.
ALLINSTANCES Specifies that all instances are to be included
in the Setup operation. This parameter is only
supported when applying a patch.
CLUSTERPASSIVE Specifies that SQL Server Setup should not manage
the SQL Server services. This option should only
be used in a non-Microsoft cluster environment.
ENU Detailed help for command line argument ENU has
not been defined yet.
FARMACCOUNT User account for running the SharePoint Central
Administration service and connecting to the
SharePoint configuration database.
FARMADMINPORT A port number used to connect to the SharePoint
Central Administration web application.
FARMPASSWORD The password for the farm account.
HELP Displays the command line parameters usage
IACCEPTSQLSERVERLICENSETERMS By specifying this parameter and accepting the
SQL Server license terms, you acknowledge that
you have read and understood the terms of use.
INDICATEPROGRESS Specifies that the detailed Setup log should be
piped to the console.
INSTANCEID Specify the Instance ID for the SQL Server
features you have specified. SQL Server directory
structure, registry structure, and service names
will reflect the instance ID of the SQL Server
instance.
INSTANCENAME Specify a default or named instance. MSSQLSERVER
is the default instance for non-Express editions
and SQLExpress for Express editions. This
parameter is required when installing the SQL
Server Database Engine (SQL), Analysis Services
(AS), or Reporting Services (RS).
PASSPHRASE A pass phrase farm administrators will use to add
application servers or Web front end servers to
an existing farm. The pass phrase must be at
least 8 characters and contain a combination of
uppercase, lowercase, numeric, and non-alphabetic
characters (such as !, $, #, %).
QUIET Setup will not display any user interface.
QUIETSIMPLE Setup will display progress only without any user
interaction.
UIMODE Valid values for the UIMode settings are Normal,
AutoAdvance.
X86 Specifies that Setup should install into WOW64.
This command line argument is not supported on an
IA64 or a 32-bit system.

Press any key to exit...

In addition to the special secret hidden parameter:

IAcceptSQLServerLicenseTerms

Which must be set otherwise it will bomb out of the installation.

I went for the following command line:

\setup.exe /quietsimple /allinstances /indicateprogress /IAcceptSQLServerLicenseTerms

The /indicateprogress flag dumps the log data to stdout, which is useful since it pipes it back through our build system for analysis. The /quietsimple flag gives you in various places a progress bar.