검색결과 리스트
글
http://www.sikurezza.org/devel/msg00122.html
Archivio: devel@sikurezza.org Soggetto: Re: recvmsg() Mittente: Mauro Tortonesi Data: 19 May 2002 20:49:01 -0000
On Fri, 17 May 2002, Kundera wrote: > Ciao a tutti, vorrei sapere sta cosa, utilizzando un > sok=socket(AF_INET6,SOCK_RAW,IPPROTO_ICMPV6) e la n=recvmsg(sok,&msg,0) > l'indirizzo ipv6 del pacchetto in arrivo dove viene messo!? dalla manpage di recvmsg: The recvmsg call uses a msghdr structure to minimize the number of directly supplied parameters. This structure has the following form, as defined in <sys/socket.h>: struct msghdr { void * msg_name; /* optional address */ socklen_t msg_namelen; /* size of address */ struct iovec * msg_iov; /* scatter/gather array */ size_t msg_iovlen; /* # elements in msg_iov */ void * msg_control; /* ancillary data, see below */ socklen_t msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ }; Here msg_name and msg_namelen specify the source address if the socket is unconnected; msg_name may be given as a null pointer if no names are desired or required. The fields msg_iov and msg_iovlen describe scatter-gather locations, as discussed in readv(2). The field msg_control, which has length msg_controllen, points to a buffer for other protocol control related messages or miscellaneous ancillary data. When recvmsg is called, msg_controllen should contain the length of the available buffer in msg_control; upon return from a successful call it will contain the length of the control message sequence. quindi basta fare: /* occhio ai jumbo datagrams!!! non e' detto che un buffer di 64kb sia * sufficiente */ const size_t BUFFER_LENGHT = 65536; int ret; uint8_t *my_buffer; struct msghdr msg; struct iovec iov; struct sockaddr_storage ss; struct sockaddr_in6 *sin6; memset(&msg, 0, sizeof(msg)); my_buffer = (uint8_t *)malloc(BUFFER_LENGTH); if (my_buffer == NULL) exit(EXIT_FAILURE); /* qui setti correttamente il buffer di destinazione */ iov.iov_base = my_buffer; iov.iov_len = BUFFER_LENGHT; msg.msg_name = &ss; msg.msg_namelen = sizeof(ss); msg.msg_iov = &iov; msg.msg_iovlen = 1; ret = recvmsg(sok, &msg, 0); /* qui controlli che non ci siano stati errori */ ... sin6 = (struct sockaddr_in6 *)&ss; e a questo punto ti ritrovi nella struttura sin6 (e piu' precisamente nel campo sin6_addr) l'indirizzo ipv6 del mittente. comunque se non vuoi allocare un buffer di 128 byte (sizeof(struct sockaddr_storage) ritorna 128 bytes) solo per ottenere l'indirizzo ipv6 del mittente puoi procedere alla estrapolazione dell'indirizzo ipv6 del mittente utilizzando un altro metodo (molto piu' complesso) previsto dallo rfc2292, che fa uso degli "ancillary data objects". vedi piu' sotto. > ho anche a disposizione l'header ipv6 in arrivo da qualche parte? no, la funzione recvmsg _NON_ ti restituisce l'intero pacchetto ipv6 (al contrario di ipv4). dal draft-ietf-ipngwg-rfc2292bis-07.txt (che e' destinato a sostituire lo rfc2292) sezione 3, pagina 19: 3. IPv6 Raw Sockets [...] Another difference from IPv4 raw sockets is that complete packets (that is, IPv6 packets with extension headers) cannot be sent or received using the IPv6 raw sockets API. Instead, ancillary data objects are used to transfer the extension headers and hoplimit information, as described in Section 6. Should an application need access to the complete IPv6 packet, some other technique, such as the datalink interfaces BPF or DLPI, must be used. pertanto la situazione si complica enormemente. innanzi tutto devi dire alla socket di fornirti i dati sul mittente: int on = 1; setsockopt(sok, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)); poi devi preparare un buffer per gli ancillary data objects restituiti da recvmsg, e quando ricevi un pacchetto devi andare ad analizzare la struttura in6_pktinfo che ti viene restituita seguendo la seguente procedura: /* 1kb e' anche troppo, ma meglio stare sul sicuro */ const size_t ADO_BUF_SIZE = 1024; const size_t BUFFER_LENGHT = 65536; int ret; uint8_t *ado_buffer; uint8_t *my_buffer; struct msghdr msg; struct iovec iov; int found = 0; struct in6_pktinfo info; struct cmsghdr *cm; struct in6_addr sender_address; ado_buffer = (uint8_t *)malloc(ADO_BUF_SIZE); if (ado_buffer == NULL) exit(EXIT_FAILURE); my_buffer = (uint8_t *)malloc(BUFFER_LENGTH); if (my_buffer == NULL) exit(EXIT_FAILURE); /* qui setti correttamente il buffer di destinazione */ iov.iov_base = my_buffer; iov.iov_len = BUFFER_LENGHT; memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = ado_buffer; msg.msg_controlen = ADO_BUF_SIZE; ret = recvmsg(sok, &msg, 0); /* qui controlli che non ci siano stati errori */ ... for (cm = CMSG_FIRSTHDR(&msg); cm != NULL; cm = CMSG_NXTHDR(&msg, cm)) { if (cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO && cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) { info = *(struct in6_pktinfo*)CMSG_DATA(cm); found = 1; break; } } sender_address = info.ipi6_addr; spero di essere stato chiaro anche se sono almeno due anni che non uso le raw socket. comunque la tua domanda mi sembra un po' off-topic per questa lista. ti consiglio di dare un'occhiata al mio sito: http://project6.ferrara.linux.it che si occupa esclusivamente di ipv6 e di iscriverti a qualcuna delle nostre mailing list (ad esempio project6-it e projec6-devel). p.s. scusa la mia insana curiosita', ma che tipo di software stai scrivendo? l'ultima volta che ho lavorato sulle raw socket icmpv6 e' stato quando ho fatto il porting del ping di netkit-base ad ipv6 ;-) -- Aequam memento rebus in arduis servare mentem... Mauro Tortonesi mauro@ferrara.linux.it Ferrara Linux User Group http://www.ferrara.linux.it Project6 - IPv6 for Linux http://project6.ferrara.linux.it ________________________________________________________ http://www.sikurezza.org - Italian Security Mailing List
'Linux > C/C++' 카테고리의 다른 글
LFS (Large File Support) (0) | 2012.07.11 |
---|---|
C 언어 레퍼런스 - setvbuf 함수 (0) | 2012.07.11 |
Socket Programming (sendmsg(), recvmsg() example) (0) | 2012.07.11 |
sendmsg(2) - Linux man page (0) | 2012.07.11 |
recvmsg(2) - Linux man page (0) | 2012.07.11 |
RECENT COMMENT