X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=support%2Fsdk%2Fc%2Fblip%2Fdriver%2Fradvd-1.0%2Frecv.c;fp=support%2Fsdk%2Fc%2Fblip%2Fdriver%2Fradvd-1.0%2Frecv.c;h=18275c60c663235a2b0919dc828b64447490e233;hb=e9bfab607e051bae6afb47b44892ce37541d1b44;hp=0000000000000000000000000000000000000000;hpb=adf1de6c009d13b7b52e68535c63b28f59c97400;p=tinyos-2.x.git diff --git a/support/sdk/c/blip/driver/radvd-1.0/recv.c b/support/sdk/c/blip/driver/radvd-1.0/recv.c new file mode 100644 index 00000000..18275c60 --- /dev/null +++ b/support/sdk/c/blip/driver/radvd-1.0/recv.c @@ -0,0 +1,119 @@ +/* + * $Id$ + * + * Authors: + * Pedro Roque + * Lars Fenneberg + * + * This software is Copyright 1996,1997 by the above mentioned author(s), + * All Rights Reserved. + * + * The license which is distributed with this software in the file COPYRIGHT + * applies to this software. If your distribution is missing this file, you + * may request it from . + * + */ + +#include "config.h" +#include "includes.h" +#include "radvd.h" + +int +recv_rs_ra(int sock, unsigned char *msg, struct sockaddr_in6 *addr, + struct in6_pktinfo **pkt_info, int *hoplimit) +{ + struct msghdr mhdr; + struct cmsghdr *cmsg; + struct iovec iov; + static unsigned char *chdr = NULL; + static unsigned int chdrlen = 0; + int len; + fd_set rfds; + + if( ! chdr ) + { + chdrlen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + + CMSG_SPACE(sizeof(int)); + if ((chdr = malloc(chdrlen)) == NULL) { + flog(LOG_ERR, "recv_rs_ra: malloc: %s", strerror(errno)); + return -1; + } + } + + FD_ZERO( &rfds ); + FD_SET( sock, &rfds ); + + if( select( sock+1, &rfds, NULL, NULL, NULL ) < 0 ) + { + if (errno != EINTR) + flog(LOG_ERR, "select: %s", strerror(errno)); + + return -1; + } + + iov.iov_len = MSG_SIZE; + iov.iov_base = (caddr_t) msg; + + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_name = (caddr_t)addr; + mhdr.msg_namelen = sizeof(*addr); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = (void *)chdr; + mhdr.msg_controllen = chdrlen; + + len = recvmsg(sock, &mhdr, 0); + + if (len < 0) + { + if (errno != EINTR) + flog(LOG_ERR, "recvmsg: %s", strerror(errno)); + + return len; + } + + *hoplimit = 255; + + for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) + { + if (cmsg->cmsg_level != IPPROTO_IPV6) + continue; + + switch(cmsg->cmsg_type) + { +#ifdef IPV6_HOPLIMIT + case IPV6_HOPLIMIT: + if ((cmsg->cmsg_len == CMSG_LEN(sizeof(int))) && + (*(int *)CMSG_DATA(cmsg) >= 0) && + (*(int *)CMSG_DATA(cmsg) < 256)) + { + *hoplimit = *(int *)CMSG_DATA(cmsg); + } + else + { + flog(LOG_ERR, "received a bogus IPV6_HOPLIMIT from the kernel! len=%d, data=%d", + cmsg->cmsg_len, *(int *)CMSG_DATA(cmsg)); + return (-1); + } + break; +#endif /* IPV6_HOPLIMIT */ + case IPV6_PKTINFO: + if ((cmsg->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) && + ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex) + { + *pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); + } + else + { + flog(LOG_ERR, "received a bogus IPV6_PKTINFO from the kernel! len=%d, index=%d", + cmsg->cmsg_len, ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex); + return (-1); + } + break; + } + } + + dlog(LOG_DEBUG, 4, "recvmsg len=%d", len); + + return len; +}