libmdn(3)

NAME
libmdn - Mulitilingual Domain Name Handling Library

SYNOPSIS
#include <mdn/api.h>
mdn_result_t
mdn_nameinit(void)
mdn_result_t
mdn_encodename(int actions, const char *from, char *to, size_t tolen)
mdn_result_t
mdn_decodename(int actions, const char *from, char *to, size_t tolen)
char *
mdn_result_tostring(mdn_result_t result)

OVERVIEW
The libmdn library supports various manipulations of multilingual domain names, including:

    -   encoding convesion

    -   normalization

Libmdn is designed according to IDNA framework where each application must do necessary preparations for the multilingual domain names before passing them to the resolver.

To help applications do the preparation, libmdn provides easy-to-use, high-level interface for the work.

This manual describes only a small subset of the API that libmdn provides, most important functions for application programmers. For other API, please refer to the mDNkit's specification document (which is not yet available) or the libmdn's header files typically found under `/usr/local/include/mdn/' on your system.

DESCRIPTION

The mdn_nameinit function initializes the whole library, and reads the default configuration file mdn.conf, which includes configuration parameters for multilingual domain name preparation. If mdn_nameinit is called more than once, the library initialization will take place only at the first call while the configuration file will be (re)read at every call.

If there are no errors, mdn_nameinit returns mdn_success. Otherwise, the returned value indicates the cause of the error. See the section ``RETURN VALUES'' below for the error codes.

Usually you don't have to call this function explicitly because it is implicitly called when mdn_encodename or mdn_decodename is first called without prior calling of mdn_nameinit.

mdn_encodename function performs normalization and encoding conversion on the multilingual domain name specified by from, and stores the result to to, whose length is specified by tolen. actions is a bitwise-OR of the following flags, specifying which subprocesses in the encoding process are to be employed.
    #define MDN_LOCALCONV 0x0001 /* Local encoding <-> UTF-8 conversion */
    #define MDN_IDNCONV   0x0002 /* UTF-8 <-> ACE conversion */
    #define MDN_NAMEPREP  0x0004 /* NAMEPREP */
    #define MDN_UNASCHECK 0x0008 /* Unassigned code point check */
    #define MDN_DELIMMAP  0x0100 /* Delimiter mapping */
    #define MDN_LOCALMAP  0x0200 /* Local mapping */

Details of this encoding process can be found in the section ``NAME ENCODING''.

For ordinary application, the following macro is provided for the convenience.
    #define MDN_ENCODE_APP \
      (MDN_LOCALCONV|MDN_DELIMMAP|MDN_LOCALMAP|MDN_NAMEPREP|MDN_IDNCONV)

mdn_decodename function performs the reverse of mdn_encodename. It converts the multilingual domain name given by from, which is represented in a special encoding called ACE, to the application's local codeset and stores into to, whose length is specified by tolen. actions specifies which subprocesses in decoding process take place, as in mdn_encodename, except that only MDN_IDNCONV, MDN_NAMEPREP and MDN_LOCALCONV are allowed. Details of this decoding process can be found in the section ``NAME DECODING''.

For ordinary application, the following macro is provided for the convenience.
    #define MDN_DECODE_APP    (MDN_IDNCONV|MDN_NAMEPREP|MDN_LOCALCONV)

All of the functions above return error code of type mdn_result_t. All codes other than mdn_success indicates some kind of failure. mdn_result_tostring function takes an error code result and returns a pointer to the corresponding message string.

NAME ENCODING
Name encoding is a process that transforms the specified multilingual domain name to a certain string suitable for name resolution. libmdn's name encoding process consists of the following steps.

(1) Encoding conversion (local codeset to UCS)
    Convert the encoding of the given domain name to Unicode/ISO10646 UTF-8 format string. The source encoding must be one of the two encodings below:

    -   The application's local encoding (codeset).

    -   ACE specified by the configuration file.
The latter is suppored because name decoding process may produce ACE strings when its attempt to convert to the local encoding fails. See the section ``NAME DECODING'' for details.

(2) Local mapping
    Apply any locale/language-specific mapping. This process is further divided into two subprocesses:

    (2-1) Delimiter mapping
        Map certain characters to the domain name delimiter (U+002E).

    (2-2) Local mapping based on TLD
        Apply character mapping whose rule is determined by the TLD of the name.

(3) NAMEPREP
    Perform name preparation (NAMEPREP), which is a standard process for normalizing multilingual domain names. This process includes checking of characters which are not allowed in multilingual domain names.

(4) Encoding conversion (UCS to ACE)
    Convert the NAMEPREPed name to a special encoding designed for representing multilingual domain names
    The encoding is also known as ACE (ASCII Compatible Encoding) since a string in the encoding is just like a traditional ASCII domain name consisting of only letters, numbers and hyphens.

There are many configuration parameters for this process, such as the ACE or the local mapping rules. These parameters are read from the default mDNkit's configuration file, mdn.conf. See mdn.conf(5) for details.

The libmdn API allows to skip some of these subprocesses. For example step (1) can be skipped if you have names already in UTF-8 format.

NAME DECODING
Name decoding is a reverse process of the name encoding. It transforms the specified multilingual domain name in a special encoding suitable for name resolution to the normal name string in the application's current codeset. However, name encoding and name decoding are not symmetric. Name decoding doesn't perform local mapping. Both name encoding and decoding do NAMEPREP, but decoding does it to verfiy a name, while encoding does it to normalize a name.

libmdn's name decoding process consists of the following steps.

(1) Encoding conversion (ACE to UCS)
    Convert the encoding of the given domain name from a special one designed for representing multilingual domain names (ACE) to Unicode/ISO10646 UTF-8.

(2) NAMEPREP check
    Perform name preparation (NAMEPREP) as also done in name encoding, and compare the result of NAMEPREP and the given UCS name. If the NAMEPREP is failed or the names are different, the given name is considered as invalid domain name. It contains a character which is never seen in a NAMEPREPed domain name.

(3) Encoding conversion (UCS to local codeset)
    Convert the encoding of the name from UTF-8 to the application's local codeset. The local codeset is determined by the application's locale.
    However, it is possible that the conversion to the application's local codeset fails because the name includes some characters which don't have mappings to the local codeset. In this case, libmdn tries instead to convert to ACE specified by the configuration file.

The configuration parameters for this process, are also read from the configuration file mdn.conf.

The libmdn API allows to skip some of these subprocesses. For example step (2) can be skipped if you want a name in UTF-8 format.

RETURN VALUES
Most of the libmdn API functions return values of type mdn_result_t in order to indicate the status of the call. The following is a complete list of the status codes. Note that some of them are never returned by the functions described in this manual.

mdn_success
    Not an error. The call succeeded.

mdn_notfound
    Specified information does not exist.

mdn_invalid_encoding
    The encoding of the specified string is invalid.

mdn_invalid_syntax
    There is a syntax error in the configuration file.

mdn_invalid_name
    The specified name is not valid.

mdn_invalid_message
    The specified DNS message is not valid.

mdn_invalid_action
    The specified action contains invalid flags.

mdn_invalid_codepoint
    The specified Unicode code point value is not valid.

mdn_buffer_overflow
    The specified buffer is too small to hold the result.

mdn_noentry
    The specified key does not exist in the hash table.

mdn_nomemory
    Memory allocation using malloc failed.

mdn_nofile
    The specified file could not be opened.

mdn_nomapping
    Some characters do not have the mapping to the target character set.

mdn_context_required
    Context information is required.

mdn_prohibited
    The specified string contains some prohibited characters.

mdn_failure
    Generic error which is not covered by the above codes.

EXAMPLES
To get the address of a multilingual domain name in the application's local codeset, use mdn_encodename to convert the name to the format suitable for passing to resolver functions.
    mdn_result_t r;
    char ace_name[256];
    struct hostent *hp;
    ...
    r = mdn_encodename(MDN_ENCODE_APP, name, ace_name,
                       sizeof(ace_name));
    if (r != mdn_success) {
        fprintf(stderr, "mdn_encodename failed: %s\n",
                mdn_result_tostring(r));
        exit(1);
    }
    hp = gethostbyname(ace_name);
    ...

To decode the multilingual domain name returned from a resolver function, use mdn_decodename.
    mdn_result_t r;
    char local_name[256];
    struct hostent *hp;
    ...
    hp = gethostbyname(name);
    r = mdn_decodename(MDN_DECODE_APP, hp->h_name, local_name,
                       sizeof(local_name));
    if (r != mdn_success) {
        fprintf(stderr, "mdn_decodename failed: %s\n",
                mdn_result_tostring(r));
        exit(1);
    }
    printf("name: %s\n", local_name);
    ...

FILES
@sysconfdir@/mdn.conf

SEE ALSO
mdn.conf(5)