Merge branch 'tomato-ND-USBmod' into tomato-RT
[tomato.git] / release / src / router / radvd / recv.c
blobaa5a19e28c265d4a3561d53ce6f78a25a90d8e5d
1 /*
2 * $Id: recv.c,v 1.14 2011/02/06 03:41:38 reubenhwk Exp $
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Lars Fenneberg <lf@elemental.net>
8 * This software is Copyright 1996,1997 by the above mentioned author(s),
9 * All Rights Reserved.
11 * The license which is distributed with this software in the file COPYRIGHT
12 * applies to this software. If your distribution is missing this file, you
13 * may request it from <pekkas@netcore.fi>.
17 #include "config.h"
18 #include "includes.h"
19 #include "radvd.h"
21 int
22 recv_rs_ra(unsigned char *msg, struct sockaddr_in6 *addr,
23 struct in6_pktinfo **pkt_info, int *hoplimit)
25 struct msghdr mhdr;
26 struct cmsghdr *cmsg;
27 struct iovec iov;
28 static unsigned char *chdr = NULL;
29 static unsigned int chdrlen = 0;
30 int len;
31 fd_set rfds;
33 if( ! chdr )
35 chdrlen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
36 CMSG_SPACE(sizeof(int));
37 if ((chdr = malloc(chdrlen)) == NULL) {
38 flog(LOG_ERR, "recv_rs_ra: malloc: %s", strerror(errno));
39 return -1;
43 FD_ZERO( &rfds );
44 FD_SET( sock, &rfds );
46 if( select( sock+1, &rfds, NULL, NULL, NULL ) < 0 )
48 if (errno != EINTR)
49 flog(LOG_ERR, "select: %s", strerror(errno));
51 return -1;
54 iov.iov_len = MSG_SIZE_RECV;
55 iov.iov_base = (caddr_t) msg;
57 memset(&mhdr, 0, sizeof(mhdr));
58 mhdr.msg_name = (caddr_t)addr;
59 mhdr.msg_namelen = sizeof(*addr);
60 mhdr.msg_iov = &iov;
61 mhdr.msg_iovlen = 1;
62 mhdr.msg_control = (void *)chdr;
63 mhdr.msg_controllen = chdrlen;
65 len = recvmsg(sock, &mhdr, 0);
67 if (len < 0)
69 if (errno != EINTR)
70 flog(LOG_ERR, "recvmsg: %s", strerror(errno));
72 return len;
75 *hoplimit = 255;
77 for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mhdr, cmsg))
79 if (cmsg->cmsg_level != IPPROTO_IPV6)
80 continue;
82 switch(cmsg->cmsg_type)
84 #ifdef IPV6_HOPLIMIT
85 case IPV6_HOPLIMIT:
86 if ((cmsg->cmsg_len == CMSG_LEN(sizeof(int))) &&
87 (*(int *)CMSG_DATA(cmsg) >= 0) &&
88 (*(int *)CMSG_DATA(cmsg) < 256))
90 *hoplimit = *(int *)CMSG_DATA(cmsg);
92 else
94 flog(LOG_ERR, "received a bogus IPV6_HOPLIMIT from the kernel! len=%d, data=%d",
95 cmsg->cmsg_len, *(int *)CMSG_DATA(cmsg));
96 return (-1);
98 break;
99 #endif /* IPV6_HOPLIMIT */
100 case IPV6_PKTINFO:
101 if ((cmsg->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) &&
102 ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex)
104 *pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
106 else
108 flog(LOG_ERR, "received a bogus IPV6_PKTINFO from the kernel! len=%d, index=%d",
109 cmsg->cmsg_len, ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex);
110 return (-1);
112 break;
116 dlog(LOG_DEBUG, 4, "recvmsg len=%d", len);
118 return len;