cs:bsd_sockets_-_datove_struktury

Zcela nevyhnutelné byly změny adresových struktur definovaných v hlavičkovém souboru netinet/in.h. Pro IPv6 se zavádí nová adresová rodina (address family) AF_INET6. Tato konstanta má z praktických důvodů přiřazenu stejnou číselnou hodnotu jako PF_INET6 (viz bits/socket.h):

 
 #define    AF_INET6    PF_INET6
 

Dříve se totiž obvykle kategorie konstant AF_ a PF_ vcelku libovolně zaměňovaly, RFC 3493 ale již důsledně respektuje jejich sémantickou odlišnost.

Původní API používá pro zápis adres IPv4 strukturu in_addr definovanou v Linuxu takto:

typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };

Jak je vidět, ve své podstatě jde pouze o obal pro číslo typu unsigned long. Obdobná struktura pro adresy IPv6 je už složitější, v prvním přiblížení si ji můžeme představit takto:

struct in6_addr
  {
    uint8_t s6_addr[16];
  };

Ve skutečnosti, podíváte-li se do hlavičkového souboru netinet/in.h, zjistíte, že deklarace je ještě složitější z důvodu efektivního zarovnání struktury na hranici slova pro všechny typy mikroprocesorových architektur. Těmito technickými detaily se však nebudeme zabývat.

Zajímavější je situace u adres soketů. Hlavní funkce BSD Sockets se používají univerzálně pro všechny rodiny protokolů. Adresy soketů se jim proto musí předávat v jednotné formě, tedy prostřednictvím neprůhledných (opaque) ukazatelů na abstraktní strukturu sockaddr. Ukazatele na struktury soketových adres konkrétních rodin protokolů je tudíž třeba pro tento účel přetypovat.

Adresy klasických internetové soketů se skládají, jak víme, z dvojice (IP adresa, TCP/UDP port). Příslušná struktura sockaddr_in je definována takto:

struct sockaddr_in
  {
    unsigned short int sin_family;    /* Address family */
    uint16_t sin_port;                /* Port number */
    struct in_addr sin_addr;          /* Internet address */
    unsigned char sin_zero[8];        /* Padding */
  };

Její délka je pomocí 8 bajtů vaty (padding) dorovnána na velikost abstraktní struktury sockaddr. Tuto rezervu si zřejmě designéři BSD Sockets ponechávali pro budoucí verze protokolu IP. Jak se zdá, ani ve snu je nenapadlo, že by se měla délka IP adresy dostat až na 128 bitů. Nicméně stalo se a do sockaddr_in se už nevejde ani samotná adresa IPv6. Proto se rovněž musela definovat nová struktura pro adresu soketu IPv6:

struct sockaddr_in6
  {
    unsigned short int sin6_family;  /* Address family */
    uint16_t sin6_port;              /* Port number */
    uint32_t sin6_flowinfo;          /* Traffic class&flow info */
    struct in6_addr sin6_addr;       /* IPv6 address */
    uint32_t sin6_scope_id;          /* IPv6 scope-id */
  };

Vidíme zde i další nové položky:

  • sin6_flowinfo obsahuje údaje ze dvou polí hlavičky IPv6: třída provozu (traffic class) a značka toku (flow label).
  • sin6_scope_id určuje síťová rozhraní patřící do stejného dosahu (address scope) jako použitá adresa.

Pro pořádek ještě dodejme, že všechny vícebajtové položky struktur (včetně šestnáctibajtové adresy IPv6) je nutno ukládat v tzv. síťovém pořadí bajtů (NBO–Network Byte Order), který se v kontextu mikroprocesorových architektur nazývá big endian. Na strojích s procesory Intel (i jiných) proto musíme vždy použít konverzní funkce htonl() nebo htons().

Poslední úprava:: 25.07.2019 13:11