Subject: (IPng 6506) Re: Basic API Status 8/31/98

From: Mukesh Kacker <[email-masked]>
Date: Sat, 19 Sep 1998 15:44:48 -0700 (PDT)

Jim, here is a response to one of the acitons from your IPng 6390 email.
> 
> Here is what I am waiting for:
> 
>   1.  Mukesh and Craig - Proposed compromised solution on sockaddr_in6
>       array/structure/storage solution with text.
> 

The text and "code" gets a bit more complex but so are the demands
on this new data structure. (Taking care of alignment issues in APIs
is unusual). I hope it is comprehensible.

======================================================================

Make the following changes to Section 3.10 (Portability Additions)
The lines prefixed with ">" are quotes from the current draft text
where changes are suggested.

> 
> 
>    One simple additions to the sockets API can help application writers.  |
> 
REPLACE above text with following:

"
One simple addition to the sockets API can help application writers
is the "stuct sockaddr_storage". This data structure can simplify writing
code portable across multiple address families and platforms. This
data structure is designed with the following goals.

        - It has a large enough implementation specific maximum size to store
          the desired set of protocol specific socket address data structures
          Specifically, it is at least large enough to accommodate sockaddr_in
          and sockaddr_in6 and possibly other protocol specific socket
          addresses too.
        - It is aligned at an appropriate boundary so protocol specific socket
          address data structure pointers can be cast to it and access their
          fields without alignment problems.
         (e.g. pointers to sockaddr_in6 and/or sockaddr_in can be cast to it
          and access fields without alignment problems).
        - It has the initial field(s) isomorphic to the fields of the
          "struct sockaddr" data structure on that implementation which
          can be used as a discriminants for deriving the protocol in use.
          These initial field(s) would on most implementations either be a
          single field of type "sa_family_t" (isomorphic to sa_family field,
          16 bits) or two fields of type uint8_t and sa_family_t respectively,
          (isomorphic to sa_len and sa_family_t, 8 bits each).

An example implementation design of such a data structure would be as follows.
"

>           struct sockaddr_storage {
>           char   _ss_maxsize[128];   /* Implementation Specific */
>            /*
>             *  Plus implementation specific fields to ensure sufficient
>             *  alignment.
>             *
>             */
>        };
> 

REPLACE above text with following.

/*
 * Desired design of maximum size and alignment
 */
#define _SS_MAXSIZE    128  /* Implementation specific max size */
#define _SS_ALIGNSIZE  (sizeof (int64_t))
                           /* Implementation specific desired alignment */

/*
 * Definitions used for sockaddr_storage structure paddings design.
 */
#define _SS_PAD1SIZE   (_SS_ALIGNSIZE - sizeof (sa_family_t))
#define _SS_PAD2SIZE   (_SS_MAXSIZE - (sizeof (sa_family_t)+ \
                              _SS_PAD1SIZE + _SS_ALIGNSIZE))
struct sockaddr_storage {
    sa_family_t  ss_family;     /* address family */
    /* Following fields are implementation specific */
    char      _ss_pad1[_SS_PAD1SIZE];
                                /* 6 byte pad, this is to make implementation
                                /* specific pad upto alignment field that */
                                /* follows explicit in the data structure */
    int64_t      _ss_align;     /* field to force desired structure */
                                /* storage alignment */
    char         _ss_pad2[_SS_PAD2SIZE];
                               /* 112 byte pad to achieve desired size, */
                               /* _SS_MAXSIZE value minus size of ss_family */
                               /* _ss_pad1, _ss_align fields is 112 */
};

On implementations where sockaddr data structure includes a "sa_len", field
this data structure would look like 

/*
 * Definitions used for sockaddr_storage structure paddings design.
 */
#define _SS_PAD1SIZE (_SS_ALIGNSIZE - \
                            (sizeof (uint8_t) + sizeof (sa_family_t))
#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (sa_family_t)+ \
                              _SS_PAD1SIZE + _SS_ALIGNSIZE))
struct sockaddr_storage {
    uint8_t      ss_len         /* address length */
    sa_family_t  ss_family;     /* address family */
    /* Following fields are implementation specific */
    char         _ss_pad1[_SS_PAD1SIZE];
                            /* 6 byte pad, this is to make implementation
                            /* specific pad upto alignment field that */
                            /* follows explicit in the data structure */
    int64_t      _ss_align;  /* field to force desired structure */
                             /* storage alignment */
    char         _ss_pad2[_SS_PAD2SIZE];
                             /* 112 byte pad to achieve desired size, */
                             /* _SS_MAXSIZE value minus size of ss_len, */
                             /* ss_family,_ss_pad1, _ss_align fields is 112 */
};

The above example implementation illustrates a data structure which will
align on a 64 bit boundary. An implementation specific field
"_ss_align" along "_ss_pad1" is used to force a 64-bit alignment which
covers proper alignment good enough for needs of sockaddr_in6 (IPv6),
sockaddr_in (IPv4) address data structures.
The size of padding fields _ss_pad1 depends on the chosen alignment boundary.
The size of padding field _ss_pad2 depends on the value of overall size
chosen for the total size of the structure. This size and alignment are
represented in the above example by implementation specific (not required)
constants  _SS_MAXSIZE (chosen value 128) and _SS_ALIGNMENT
(with chosen value 8). Constants _SS_PAD1SIZE (derived value 6) and
_SS_PAD2SIZE (derived value 112) are also for illustration and not required.
The implementation specific definitions and structure field names above
start with an underscore to denote implementation private namespace.
Portable code is not expected to access or reference those fields or
constants.

> This structure solves the problem that you don't know how big the         |
>    retrieve buffer for a socket address structure needs to be until you   |
>    have received that structure (e.g., getpeername()). 

The sockaddr_storage structure solves the problem of declaring storage for
automatic variables which is large enough and aligned enough for storing
socket address data structure of any family. For example, code with a file
descriptor and without the context of the address family can pass a pointer
to a variable of this type where a pointer to a socket address structure is
expected in calls such as getpeername() and determine the address family by
accessing the received content after the call.

The sockaddr_storage structure may also be useful and applied to certain
other interfaces where a generic socket address large enough and aligned
for use with multiple address families may be needed. A discussion of those
interfaces is outside the scope of this document.

>  Also, much        |
>    existing code assumes that any socket address structure can fit in a   |
>    generic sockaddr structure.  While this has been true for IPv4 socket  |
>    address structures, it has always been false for Unix domain socket    |
>    address structures (but in practice this has not been a problem) and   |
>    it is also false for IPv6 socket address structures (which can be a    |
>    problem).                                                              |
> 
>    So now an application can to the following:                            |
> 
>                struct sockaddr_storage ss;
>             ....
>             struct sockaddr_in6 *sin6;
> 
>             sin6 = (struct sockaddr_in6 *) &ss;
> 
> 
> Each implementation can add whatever fields it needs to get appropriate   |
>    aligment.                                                              |
> 

In the above text,
	- CORRECT a minor typo by modifying
          "...can to following:" to "...can do following"

        - DELETE the last sentence (as that stuff is stated
           elsewhere/differently now). That is, delete the following:

          "Each implementation ....appropriate alignment"

======================================================================

-Mukesh Kacker
 Sun Microsystems Inc.
 [email-masked]
--------------------------------------------------------------------
IETF IPng Working Group Mailing List
IPng Home Page:                      http://playground.sun.com/ipng
FTP archive:                      ftp://playground.sun.com/pub/ipng
Direct all administrative requests to [email-masked]
--------------------------------------------------------------------