Divided the logic of the capwap_recvfrom function into two distinct functions:
poll (capwap_wait_recvready) and recv (capwap_recvfrom_fd)
This commit is contained in:
parent
769d0f414e
commit
6ee885f9b6
@ -308,25 +308,14 @@ int capwap_compare_ip(struct sockaddr_storage* addr1, struct sockaddr_storage* a
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive packet with timeout */
|
/* Wait receive packet with timeout */
|
||||||
int capwap_recvfrom(struct pollfd* fds, int fdscount, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, struct timeout_control* timeout) {
|
int capwap_wait_recvready(struct pollfd* fds, int fdscount, struct timeout_control* timeout) {
|
||||||
int i;
|
int i;
|
||||||
int polltimeout = -1;
|
|
||||||
int readysocket;
|
int readysocket;
|
||||||
int result = CAPWAP_RECV_ERROR_SOCKET;
|
int polltimeout = -1;
|
||||||
|
|
||||||
ASSERT(fds);
|
ASSERT(fds);
|
||||||
ASSERT(fdscount > 0);
|
ASSERT(fdscount > 0);
|
||||||
ASSERT(buffer != NULL);
|
|
||||||
ASSERT(size != NULL);
|
|
||||||
ASSERT(*size > 0);
|
|
||||||
ASSERT(recvfromaddr != NULL);
|
|
||||||
ASSERT(recvtoaddr != NULL);
|
|
||||||
|
|
||||||
memset(recvfromaddr, 0, sizeof(struct sockaddr_storage));
|
|
||||||
if (recvtoaddr) {
|
|
||||||
memset(recvtoaddr, 0, sizeof(struct sockaddr_storage));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check timeout */
|
/* Check timeout */
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
@ -349,101 +338,142 @@ int capwap_recvfrom(struct pollfd* fds, int fdscount, void* buffer, int* size, s
|
|||||||
/* Get packet from only one socket */
|
/* Get packet from only one socket */
|
||||||
for (i = 0; i < fdscount; i++) {
|
for (i = 0; i < fdscount; i++) {
|
||||||
if ((fds[i].revents & POLLIN) != 0) {
|
if ((fds[i].revents & POLLIN) != 0) {
|
||||||
int packetsize = -1;
|
return i;
|
||||||
socklen_t sendaddresslen = sizeof(struct sockaddr_storage);
|
|
||||||
struct sockaddr_storage sockinfo;
|
|
||||||
socklen_t sockinfolen = sizeof(struct sockaddr_storage);
|
|
||||||
struct iovec iov;
|
|
||||||
struct msghdr msgh;
|
|
||||||
struct cmsghdr* cmsg;
|
|
||||||
char cbuf[256];
|
|
||||||
|
|
||||||
/* Information socket */
|
|
||||||
memset(&sockinfo, 0, sizeof(struct sockaddr_storage));
|
|
||||||
if (getsockname(fds[i].fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
iov.iov_base = buffer;
|
|
||||||
iov.iov_len = *size;
|
|
||||||
|
|
||||||
memset(&msgh, 0, sizeof(struct msghdr));
|
|
||||||
msgh.msg_control = cbuf;
|
|
||||||
msgh.msg_controllen = sizeof(cbuf);
|
|
||||||
msgh.msg_name = recvfromaddr;
|
|
||||||
msgh.msg_namelen = sendaddresslen;
|
|
||||||
msgh.msg_iov = &iov;
|
|
||||||
msgh.msg_iovlen = 1;
|
|
||||||
msgh.msg_flags = 0;
|
|
||||||
|
|
||||||
/* Receive packet with recvmsg */
|
|
||||||
do {
|
|
||||||
packetsize = recvmsg(fds[i].fd, &msgh, 0);
|
|
||||||
} while ((packetsize < 0) && ((errno == EAGAIN) || (errno == EINTR)));
|
|
||||||
|
|
||||||
if (packetsize > 0) {
|
|
||||||
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
|
||||||
#ifdef IP_PKTINFO
|
|
||||||
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
|
||||||
struct in_pktinfo* i = (struct in_pktinfo*)CMSG_DATA(cmsg);
|
|
||||||
struct sockaddr_in* addr = (struct sockaddr_in*)recvtoaddr;
|
|
||||||
|
|
||||||
addr->sin_family = AF_INET;
|
|
||||||
memcpy(&addr->sin_addr, &i->ipi_addr, sizeof(struct in_addr));
|
|
||||||
addr->sin_port = ((struct sockaddr_in*)&sockinfo)->sin_port;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#elif defined IP_RECVDSTADDR
|
|
||||||
if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) {
|
|
||||||
struct in_addr* i = (struct in_addr*)CMSG_DATA(cmsg);
|
|
||||||
struct sockaddr_in* addr = (struct sockaddr_in*)recvtoaddr;
|
|
||||||
|
|
||||||
addr->sin_family = AF_INET;
|
|
||||||
memcpy(&addr->sin_addr, i, sizeof(struct in_addr));
|
|
||||||
addr->sin_port = ((struct sockaddr_in*)&sockinfo)->sin_port;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#error "No method of getting the destination ip address supported"
|
|
||||||
#endif
|
|
||||||
if ((cmsg->cmsg_level == IPPROTO_IPV6) && ((cmsg->cmsg_type == IPV6_PKTINFO) || (cmsg->cmsg_type == IPV6_RECVPKTINFO))) {
|
|
||||||
struct in6_pktinfo* i = (struct in6_pktinfo*)CMSG_DATA(cmsg);
|
|
||||||
struct sockaddr_in6* addr = (struct sockaddr_in6*)recvtoaddr;
|
|
||||||
|
|
||||||
addr->sin6_family = AF_INET6;
|
|
||||||
memcpy(&addr->sin6_addr, &i->ipi6_addr, sizeof(struct in6_addr));
|
|
||||||
addr->sin6_port = ((struct sockaddr_in6*)&sockinfo)->sin6_port;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (packetsize < 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
*size = packetsize;
|
|
||||||
result = i;
|
|
||||||
|
|
||||||
break;
|
|
||||||
} else if ((fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) != 0) {
|
} else if ((fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) != 0) {
|
||||||
break;
|
return CAPWAP_RECV_ERROR_SOCKET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (readysocket == 0) {
|
} else if (readysocket == 0) {
|
||||||
result = CAPWAP_RECV_ERROR_TIMEOUT;
|
/* Update timer for detect timeout */
|
||||||
if (timeout) {
|
if (timeout) {
|
||||||
/* Update timer for detect timeout */
|
|
||||||
capwap_update_timeout(timeout);
|
capwap_update_timeout(timeout);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (errno == EINTR) {
|
return CAPWAP_RECV_ERROR_TIMEOUT;
|
||||||
result = CAPWAP_RECV_ERROR_INTR;
|
} else if (errno == EINTR) {
|
||||||
}
|
return CAPWAP_RECV_ERROR_INTR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return CAPWAP_RECV_ERROR_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive packet from fd */
|
||||||
|
int capwap_recvfrom_fd(int fd, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr) {
|
||||||
|
int packetsize = -1;
|
||||||
|
socklen_t sendaddresslen = sizeof(struct sockaddr_storage);
|
||||||
|
struct sockaddr_storage sockinfo;
|
||||||
|
socklen_t sockinfolen = sizeof(struct sockaddr_storage);
|
||||||
|
struct iovec iov;
|
||||||
|
struct msghdr msgh;
|
||||||
|
struct cmsghdr* cmsg;
|
||||||
|
char cbuf[256];
|
||||||
|
|
||||||
|
ASSERT(fd >= 0);
|
||||||
|
ASSERT(buffer != NULL);
|
||||||
|
ASSERT(size != NULL);
|
||||||
|
ASSERT(*size > 0);
|
||||||
|
ASSERT(recvfromaddr != NULL);
|
||||||
|
ASSERT(recvtoaddr != NULL);
|
||||||
|
|
||||||
|
memset(recvfromaddr, 0, sizeof(struct sockaddr_storage));
|
||||||
|
if (recvtoaddr) {
|
||||||
|
memset(recvtoaddr, 0, sizeof(struct sockaddr_storage));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Information socket */
|
||||||
|
memset(&sockinfo, 0, sizeof(struct sockaddr_storage));
|
||||||
|
if (getsockname(fd, (struct sockaddr*)&sockinfo, &sockinfolen) < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
iov.iov_base = buffer;
|
||||||
|
iov.iov_len = *size;
|
||||||
|
|
||||||
|
memset(&msgh, 0, sizeof(struct msghdr));
|
||||||
|
msgh.msg_control = cbuf;
|
||||||
|
msgh.msg_controllen = sizeof(cbuf);
|
||||||
|
msgh.msg_name = recvfromaddr;
|
||||||
|
msgh.msg_namelen = sendaddresslen;
|
||||||
|
msgh.msg_iov = &iov;
|
||||||
|
msgh.msg_iovlen = 1;
|
||||||
|
msgh.msg_flags = 0;
|
||||||
|
|
||||||
|
/* Receive packet with recvmsg */
|
||||||
|
do {
|
||||||
|
packetsize = recvmsg(fd, &msgh, 0);
|
||||||
|
} while ((packetsize < 0) && ((errno == EAGAIN) || (errno == EINTR)));
|
||||||
|
|
||||||
|
if (packetsize > 0) {
|
||||||
|
for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
|
||||||
|
#ifdef IP_PKTINFO
|
||||||
|
if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
|
||||||
|
struct in_pktinfo* i = (struct in_pktinfo*)CMSG_DATA(cmsg);
|
||||||
|
struct sockaddr_in* addr = (struct sockaddr_in*)recvtoaddr;
|
||||||
|
|
||||||
|
addr->sin_family = AF_INET;
|
||||||
|
memcpy(&addr->sin_addr, &i->ipi_addr, sizeof(struct in_addr));
|
||||||
|
addr->sin_port = ((struct sockaddr_in*)&sockinfo)->sin_port;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#elif defined IP_RECVDSTADDR
|
||||||
|
if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) {
|
||||||
|
struct in_addr* i = (struct in_addr*)CMSG_DATA(cmsg);
|
||||||
|
struct sockaddr_in* addr = (struct sockaddr_in*)recvtoaddr;
|
||||||
|
|
||||||
|
addr->sin_family = AF_INET;
|
||||||
|
memcpy(&addr->sin_addr, i, sizeof(struct in_addr));
|
||||||
|
addr->sin_port = ((struct sockaddr_in*)&sockinfo)->sin_port;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "No method of getting the destination ip address supported"
|
||||||
|
#endif
|
||||||
|
if ((cmsg->cmsg_level == IPPROTO_IPV6) && ((cmsg->cmsg_type == IPV6_PKTINFO) || (cmsg->cmsg_type == IPV6_RECVPKTINFO))) {
|
||||||
|
struct in6_pktinfo* i = (struct in6_pktinfo*)CMSG_DATA(cmsg);
|
||||||
|
struct sockaddr_in6* addr = (struct sockaddr_in6*)recvtoaddr;
|
||||||
|
|
||||||
|
addr->sin6_family = AF_INET6;
|
||||||
|
memcpy(&addr->sin6_addr, &i->ipi6_addr, sizeof(struct in6_addr));
|
||||||
|
addr->sin6_port = ((struct sockaddr_in6*)&sockinfo)->sin6_port;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (packetsize < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Packet receive */
|
||||||
|
*size = packetsize;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive packet with timeout */
|
||||||
|
int capwap_recvfrom(struct pollfd* fds, int fdscount, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, struct timeout_control* timeout) {
|
||||||
|
int index;
|
||||||
|
|
||||||
|
ASSERT(fds);
|
||||||
|
ASSERT(fdscount > 0);
|
||||||
|
ASSERT(buffer != NULL);
|
||||||
|
ASSERT(size != NULL);
|
||||||
|
ASSERT(*size > 0);
|
||||||
|
ASSERT(recvfromaddr != NULL);
|
||||||
|
ASSERT(recvtoaddr != NULL);
|
||||||
|
|
||||||
|
/* Wait packet */
|
||||||
|
index = capwap_wait_recvready(fds, fdscount, timeout);
|
||||||
|
if (index < 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive packet */
|
||||||
|
if (!capwap_recvfrom_fd(fds[index].fd, buffer, size, recvfromaddr, recvtoaddr)) {
|
||||||
|
return CAPWAP_RECV_ERROR_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
@ -1138,12 +1168,11 @@ static short capwap_get_interface_flags(char* iface) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
strcpy(req.ifr_name, iface);
|
strcpy(req.ifr_name, iface);
|
||||||
if (ioctl(sock, SIOCGIFFLAGS, &req) < 0) {
|
if (ioctl(sock, SIOCGIFFLAGS, &req) < 0) {
|
||||||
req.ifr_flags = 0;
|
req.ifr_flags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(sock);
|
close(sock);
|
||||||
|
|
||||||
return req.ifr_flags;
|
return req.ifr_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +85,9 @@ int capwap_compare_ip(struct sockaddr_storage* addr1, struct sockaddr_storage* a
|
|||||||
|
|
||||||
int capwap_sendto(int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
|
int capwap_sendto(int sock, void* buffer, int size, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
|
||||||
int capwap_sendto_fragmentpacket(int sock, struct capwap_list* fragmentlist, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
|
int capwap_sendto_fragmentpacket(int sock, struct capwap_list* fragmentlist, struct sockaddr_storage* sendfromaddr, struct sockaddr_storage* sendtoaddr);
|
||||||
|
|
||||||
|
int capwap_wait_recvready(struct pollfd* fds, int fdscount, struct timeout_control* timeout);
|
||||||
|
int capwap_recvfrom_fd(int fd, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr);
|
||||||
int capwap_recvfrom(struct pollfd* fds, int fdscount, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, struct timeout_control* timeout);
|
int capwap_recvfrom(struct pollfd* fds, int fdscount, void* buffer, int* size, struct sockaddr_storage* recvfromaddr, struct sockaddr_storage* recvtoaddr, struct timeout_control* timeout);
|
||||||
|
|
||||||
int capwap_ipv4_mapped_ipv6(struct sockaddr_storage* source, struct sockaddr_storage* dest);
|
int capwap_ipv4_mapped_ipv6(struct sockaddr_storage* source, struct sockaddr_storage* dest);
|
||||||
|
Loading…
Reference in New Issue
Block a user