CMSG(3)

NOME
CMSG_ALIGN, CMSG_SPACE, CMSG_NXTHDR, CMSG_FIRSTHDR - accesso a dados ancilares

SINÓPSE
#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;	/* total de bytes de dados, incluindo o cabeçalho */
	int	cmsg_level;	/* protocolo original */
	int	cmsg_type;	/* tipo protocolo-específico */
/* followed by 	unsigned char	cmsg_data[]; */
};

DESCRIÇÃO
Estas macros servem para criar e acessar mensagens de controle (também chamadas dados ancilares) que não são parte do conteúdo do 'socket'. Esta informação pode incluir a interface onde o pacote foi recebido, uma miscelânea de cabeçalhos raramente usados, uma descrição de erro mais detalhada, um conjunto de descritores de arquivo ou credenciais unix. Por exemplo, pode se usar mensagens de controle para enviar campos de cabeçalho adicionais tais como opções IP. Os dados são enviados com sendmsg(2) e recebidos com recvmsg(2). Veja as manpages para mais informações.

Os dados ancilares consistem numa seqüência de struct cmsghdr seguidas de dados adicionais, que devem ser acessadas apenas com as macros descritas nesta manpage e não diretamente. Veja os tipos de mensagens de controle nas páginas de manuais dos protocolos. O tamanho máximo do 'buffer' auxiliar do 'socket' pode ser definido com net.core.optmem_max do sysctl. Ver socket(7).

CMSG_FIRSTHDR retorna um ponteiro para o primeiro cmsghdr do 'buffer' ancilar associado ao msghdr.

CMSG_NXTHDR retorna o próximo cmsghdr válido depois do cmsghdr. indicado, e retorna NULO se não houver mais espaço suficiente no 'buffer'.

CMSG_ALIGN, dado um tamanho, retorna-o incluindo o alinhamento requerido. Isto é uma expressão constante.

CMSG_SPACE retorna o número de bytes de um elemento acessório com um conteúdo do comprimento indicado. Esta expressão é constante.

CMSG_DATA retorna um ponteiro para os dados de um cmsghdr.

CMSG_LEN retorna o valor do membro cmsg_len do struct cmsghdr considerando qualquer alinhamento necessário. Ela pega o tamanho como argumento. Esta expressão é constante.

Para criar dados ancilares, inicialize o membro msg_controllen do msghdr com o comprimento do 'buffer' de mensagem de controle. Use CMSG_FIRSTHDR no msghdr para recuperar a primeira mensagem de controle e CMSG_NEXTHDR para as seguintes. Para cada mensagem de controle, inicialize cmsg_len (com CMSG_LEN), e os outros cmsghdr campos e a porção de dados com CMSG_DATA. No final, o campo msg_controllen de msghdr deve ter a soma dos comprimentos de todas as mensagens de controle CMSG_SPACE do 'buffer'. Para mais informações sobre o msghdr, veja recvmsg(2).

Quando o 'buffer' de mensagens de controle não comportar todas as mensagens, o sinalizador MSG_CTRUNC é ativado em msg_flags de msghdr.

EXEMPLO
Este código procura a opção IP_TTL num 'buffer' ancilar recebido:

    struct msghdr msgh;
    struct cmsghdr *cmsg;
    int *ttlptr;
    int received_ttl;
    /* Receber dados ancilares em 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) {
    	/*
    	 * Erro: IP_TTL desabilitado ou 'buffer' muito curto
    	 * ou erro de E/S .
    	 */
    }

O código abaixo transmite um 'array' de descritores de arquivo através de um 'socket' Unix usando SCM_RIGHTS:

    struct msghdr msg = {0};
    struct cmsghdr *cmsg;
    int myfds[NUM_FD]; /* Descritores de arquivo a transmitir. */
    char buf[CMSG_SPACE(sizeof myfds)];  /* 'buffer' de dados ancilares */
    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);
    /* Inicializar o conteúdo: */
    fdptr = (int *)CMSG_DATA(cmsg);
    memcpy(fdptr, myfds, NUM_FD * sizeof(int));
    /* Soma dos comprimentos de todas as mensagens de controle no 'buffer': */
    msg.msg_controllen = cmsg->cmsg_len;

OBSERVAÇÕES
Os dados ancilares devem ser acessados apenas com as macros definidas aqui para manter a portabilidade. CMSG_ALIGN é uma extensão linux, e deve ser evitada em programas portáveis.

No linux, CMSG_LEN, CMSG_DATA, e CMSG_ALIGN são constantes (se receberem um argumento constante), e podem ser usados para declarar o tamanho de variáveis globais. Isto pode, no entanto, não ser portável.

DE ACORDO COM
O modelo de dados ancilares segue o rascunho POSIX.1003.1g, BSD Lite 4.4, a API IPv6 avançada descrita no RFC2292 e a SUSv2. CMSG_ALIGN é uma extensão linux.

VEJA TAMBÉM
sendmsg(2), recvmsg(2).

RFC 2292.

TRADUZIDO POR LDP-BR em 21/08/2000.

  Tradução:
Paulo César Mendes <drpc@ism.com.br>

  Revisão.:
André Luiz Fassone <lonely_wolf@ig.com.br>