CMSG(3)

NAZWA
CMSG_ALIGN, CMSG_SPACE, CMSG_NXTHDR, CMSG_FIRSTHDR - dostęp do danych pomocniczych

SKŁADNIA
#include <sys/socket.h>

struct cmsghdr *CMSG_FIRSTHDR(struct msghdr *msgh);
struct cmsghdr *CMSG_NXTHDR(struct msghdr *msgh, struct cmsghdr *cmsg);
size_t CMSG_ALIGN(size_t length);
size_t CMSG_SPACE(size_t length);
size_t CMSG_LEN(size_t length);
unsigned char *CMSG_DATA(struct cmsghdr *cmsg);

struct cmsghdr {
    size_t cmsg_len;    /* Liczba bajtów danych, włączając nagłówek
                           (typ to socklen_t w POSIX) */
    int    cmsg_level;  /* Protokół źródłowy */
    int    cmsg_type;   /* Typ zależny od protokołu */
/* followed by
   unsigned char cmsg_data[]; */
};

OPIS
Makrodefinicje te służą do tworzenia i dostępu do komunikatów sterujących (zwanych również danymi pomocniczymi), które nie są częścią gniazda. Te informacje sterujące mogą zawierać: interfejs, przez który pakiet został odebrany, różne rzadko używane pola nagłówka, rozszerzony opis błędu, zestaw deskryptorów plików lub uwierzytelnień uniksowych. Na przykład, komunikaty sterujące mogą służyć do ustawiania dodatkowych pól nagłówka, takich jak opcje IP, dla wysyłanych pakietów. Dane pomocnicze są wysyłane poprzez wywołanie sendmsg(2), a odbierane poprzez wywołanie recvmsg(2). Więcej informacji znajduje się na stronach podręcznika tych poleceń.

Dane pomocnicze są ciągiem struktur struct cmsghdr z dodanymi danymi. Dostęp do tego ciągu powinien się odbywać wyłącznie przez opisane na tej stronie podręcznika makrodefinicje, nigdy zaś bezpośrednio. Dostępne rodzaje komunikatów sterujących opisano na stronach podręcznika poszczególnych protokołów. Maksymalny rozmiar bufora danych pomocniczych dla gniazda można ustawić, używając /proc/sys/net/core/optmem_max; patrz socket(7).

CMSG_FIRSTHDR() zwraca wskaźnik do pierwszego cmsghdr w buforze danych pomocniczych związanym z przekazanym msghdr.

CMSG_NXTHDR() zwraca następny poprawny cmsghdr po przekazanym cmsghdr. Zwraca NULL, gdy brak dostatecznej ilości miejsca w buforze.

CMSG_ALIGN() zwraca żądaną długość, włączając niezbędne wyrównanie. Jest to wyrażenie stałe.

CMSG_SPACE() zwraca liczbę bajtów elementu pomocniczego włączając długość, jaką zajmują przekazane dane. Jest to wyrażenie stałe.

CMSG_DATA() zwraca wskaźnik do części cmsghdr zawierającej dane.

CMSG_LEN() zwraca wartość, która ma być przechowywana w elemencie cmsg_len struktury cmsghdr, biorąc pod uwagę wszelkie niezbędne wyrównania. Jako argument pobiera długość danych. Jest to wyrażenie stałe.

Aby utworzyć dane pomocnicze, należy najpierw zainicjować element msg_controllen struktury msghdr długością bufora komunikatów sterujących. Należy użyć CMSG_FIRSTHDR() dla msghdr, aby otrzymać pierwszy komunikat sterujący, oraz CMSG_NXTHDR(), aby otrzymać wszystkie następne. Dla każdego komunikatu sterującego należy zainicjować cmsg_len (za pomocą CMSG_LEN()), inne pola nagłówka cmsghdr oraz część zawierającą dane za pomocą CMSG_DATA(). Ostatecznie pole msg_controllen struktury msghdr powinno zawierać sumę CMSG_SPACE() długości wszystkich komunikatów sterujących w buforze. Więcej informacji dotyczących msghdr znajduje się w recvmsg(2).

Gdy bufor komunikatów sterujących jest za krótki, aby przechować wszystkie komunikaty, ustawiany jest znacznik MSG_CTRUNC elementu msg_flags struktury msghdr.

ZGODNE Z
Ten model danych pomocniczych jest zgodny ze szkicem POSIX.1g, z 4.4BSD-Lite, z zaawansowanym API dla IPv6 opisanym w RFC 2292 oraz z SUSv2. CMSG_ALIGN() jest rozszerzeniem Linuksa.

UWAGI
Dla przenośności, dostęp do danych pomocniczych powinien się odbywać jedynie za pomocą opisanych tu makrodefinicji. CMSG_ALIGN() jest rozszerzeniem Linuksa i nie powinno być używane w przenośnych programach.

W Linuksie, CMSG_LEN(), CMSG_DATA() i CMSG_ALIGN() są wyrażeniami stałymi (zakładając, że ich argument jest stały) - można to wykorzystać do zadeklarowania rozmiaru zmiennych globalnych. Jednakże, może się to okazać nieprzenośnym.

PRZYKŁAD
Następujący kod poszukuje opcji IP_TTL w otrzymanym buforze pomocniczym:

struct msghdr msgh;
struct cmsghdr *cmsg;
int *ttlptr;
int received_ttl;
/* Otrzymywanie danych z zewnątrz do msgh */
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
        cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
    if (cmsg->cmsg_level == IPPROTO_IP
            && cmsg->cmsg_type == IP_TTL) {
        ttlptr = (int *) CMSG_DATA(cmsg);
        received_ttl = *ttlptr;
        break;
    }
}
if (cmsg == NULL) {
     /* Błąd: IP_TTL nie jest włączone, za mały bufor
        lub błąd wejścia/wyjścia */
}

Poniższy kod przekazuje tablicę deskryptorów plików przez gniazdo domeny UNIX SCM_RIGHTS:

struct msghdr msg = { 0 };
struct cmsghdr *cmsg;
int myfds[NUM_FD];  /* Zawiera przekazywane deskryptory plików */
int *fdptr;
union {         /* Bufor danych pomocniczych, opakowany w unię,
                   aby zapewnić jego odpowiednie wyrównanie */
    char buf[CMSG_SPACE(sizeof(myfds))];
    struct cmsghdr align;
} u;
msg.msg_control = u.buf;
msg.msg_controllen = sizeof(u.buf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * NUM_FD);
fdptr = (int *) CMSG_DATA(cmsg);    /* Inicjacja payloadu */
memcpy(fdptr, myfds, NUM_FD * sizeof(int));

ZOBACZ TAKŻE
recvmsg(2), sendmsg(2)

RFC 2292

O STRONIE
Angielska wersja tej strony pochodzi z wydania 4.07 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem https://www.kernel.org/doc/man-pages/.

TŁUMACZENIE
Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Andrzej Krzysztofowicz (PTM) <ankry@mif.pg.gda.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>.

Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 4.07 oryginału.