1/* 2 * $Id: recv.c,v 1.11 2006/10/09 06:21:59 psavola Exp $ 3 * 4 * Authors: 5 * Pedro Roque <roque@di.fc.ul.pt> 6 * Lars Fenneberg <lf@elemental.net> 7 * 8 * This software is Copyright 1996,1997 by the above mentioned author(s), 9 * All Rights Reserved. 10 * 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>. 14 * 15 */ 16 17#include <config.h> 18#include <includes.h> 19#include <radvd.h> 20#include <sys/ioctl.h> /* ioctl */ 21 22int 23recv_rs_ra(int sock, unsigned char *msg, struct sockaddr_in6 *addr, 24 struct in6_pktinfo **pkt_info, int *hoplimit) 25{ 26 struct msghdr mhdr; 27 struct cmsghdr *cmsg; 28 struct iovec iov; 29 static unsigned char *chdr = NULL; 30 static unsigned int chdrlen = 0; 31 int len; 32 fd_set rfds; 33 34 int fd; 35 36 if( ! chdr ) 37 { 38 chdrlen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + 39 CMSG_SPACE(sizeof(int)); 40 if ((chdr = malloc(chdrlen)) == NULL) { 41 flog(LOG_ERR, "recv_rs_ra: malloc: %s", strerror(errno)); 42 return -1; 43 } 44 } 45 46 FD_ZERO( &rfds ); 47 FD_SET( sock, &rfds ); 48 49 if( select( sock+1, &rfds, NULL, NULL, NULL ) < 0 ) 50 { 51 if (errno != EINTR) 52 flog(LOG_ERR, "select: %s", strerror(errno)); 53 54 return -1; 55 } 56 57 iov.iov_len = MSG_SIZE; 58 iov.iov_base = (caddr_t) msg; 59 60 memset(&mhdr, 0, sizeof(mhdr)); 61 mhdr.msg_name = (caddr_t)addr; 62 mhdr.msg_namelen = sizeof(*addr); 63 mhdr.msg_iov = &iov; 64 mhdr.msg_iovlen = 1; 65 mhdr.msg_control = (void *)chdr; 66 mhdr.msg_controllen = chdrlen; 67 68 len = recvmsg(sock, &mhdr, 0); 69 70 if (len < 0) 71 { 72 if (errno != EINTR) 73 flog(LOG_ERR, "recvmsg: %s", strerror(errno)); 74 75 return len; 76 } 77 78 *hoplimit = 255; 79 80 /* shortterm workaround to get hop limit , Bob, 07/21/2009*/ 81 fd = open("/dev/acos_nat_cli", O_RDWR); 82 83 if(fd) 84 { 85 /*Foxconn modify start by Hank 09/26/2012*/ 86 /*Fix wrong ioctl command*/ 87 ioctl(fd, _IOR(100, 174, char *), hoplimit); 88 /*Foxconn modify end by Hank 09/26/2012*/ 89 close(fd); 90 } 91 /* end of shortterm workaround to get hop limit , Bob, 07/21/2009*/ 92 93 for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) 94 { 95 if (cmsg->cmsg_level != IPPROTO_IPV6) 96 continue; 97 98 switch(cmsg->cmsg_type) 99 { 100#ifdef IPV6_HOPLIMIT 101 case IPV6_HOPLIMIT: 102 if ((cmsg->cmsg_len == CMSG_LEN(sizeof(int))) && 103 (*(int *)CMSG_DATA(cmsg) >= 0) && 104 (*(int *)CMSG_DATA(cmsg) < 256)) 105 { 106 107 *hoplimit = *(int *)CMSG_DATA(cmsg); 108 } 109 else 110 { 111 flog(LOG_ERR, "received a bogus IPV6_HOPLIMIT from the kernel! len=%d, data=%d", 112 cmsg->cmsg_len, *(int *)CMSG_DATA(cmsg)); 113 return (-1); 114 } 115 break; 116#endif /* IPV6_HOPLIMIT */ 117 case IPV6_PKTINFO: 118 if ((cmsg->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) && 119 ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex) 120 { 121 *pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); 122 } 123 else 124 { 125 flog(LOG_ERR, "received a bogus IPV6_PKTINFO from the kernel! len=%d, index=%d", 126 cmsg->cmsg_len, ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex); 127 return (-1); 128 } 129 break; 130 } 131 } 132 133 dlog(LOG_DEBUG, 4, "recvmsg len=%d", len); 134 135 return len; 136} 137