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 {
socklen_t cmsg_len; /* liczba bajtów danych, włączając nagłówek */
int cmsg_level; /* protokół źródłowy */
int cmsg_type; /* zależny od protokołu typ */
/* następuje po nim 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 otrzymywane poprzez wywołanie
recvmsg(2).
Więcej informacji znajduje się na stronach podręcznika man dla
tych poleceń.
Dane pomocnicze są ciągiem struktur
struct cmsghdr z dodanymi
danymi. Dostęp do tego ciągu powinien się odbywać
wyłącznie poprzez opisane na tej stronie podręcznika
makrodefinicje, nigdy zaś bezpośrednio. Dostępne rodzaje
komunikatów sterujących opisano na stronach podręcznika dla
poszczególnych protokołów. Maksymalny rozmiar bufora danych
pomocniczych dla gniazda można ustawić za pomocą sysctl-a
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, zadana długość, zwraca ją
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 zainicjalizować
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_NEXTHDR, aby otrzymać wszystkie
następne. Dla każdego komunikatu sterującego należy
zainicjalizować
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 dla 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.
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 == SOL_IP
&& cmsg->cmsg_type == IP_TTL) {
ttlptr = (int *) CMSG_DATA(cmsg);
received_ttl = *ttlptr;
break;
}
}
if (cmsg == NULL) {
/*
* Błąd: IP_TTL not jest włączone, za mały bufor lub
* błąd I/O.
*/
}
Poniższy kod przekazuje tablicę deskryptorów plików poprzez
gniazdo Uniksa
SCM_RIGHTS:
struct msghdr msg = {0};
struct cmsghdr *cmsg;
int myfds[NUM_FD]; /* Zawiera przekazywane deskryptory plików. */
char buf[CMSG_SPACE(sizeof myfds)]; /* bufor danych pomocniczych */
int *fdptr;
msg.msg_control = buf;
msg.msg_controllen = sizeof buf;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * NUM_FD);
/* Inicjalizacja: */
fdptr = (int *)CMSG_DATA(cmsg);
memcpy(fdptr, myfds, NUM_FD * sizeof(int));
/* Suma długości wszystkich komunikatów sterujących w buforze: */
msg.msg_controllen = cmsg->cmsg_len;
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.
ZGODNE Z¶
Ten model danych pomocniczych jest zgodny ze szkicem POSIX.1003.1g, z
4.4BSD-Lite, z zaawansowanym API dla IPv6 opisanym w RFC2292 oraz ze
specyfikacją Single Unix v2.
CMSG_ALIGN jest rozszerzeniem
Linuksa.
ZOBACZ TAKŻE¶
sendmsg(2),
recvmsg(2)
RFC 2292