version 1.2, 2015/04/20 18:10:35
|
version 1.3, 2015/04/20 18:20:34
|
|
|
#include <ctype.h> | #include <ctype.h> |
#include <string.h> | #include <string.h> |
| |
|
// #define ENABLE_TRACING 1 |
|
|
/* Include network headers */ | /* Include network headers */ |
#if defined(CONFIG_OS_WINDOWS) |
#if defined CONFIG_OS_WINDOWS |
|
|
# include <winsock2.h> | # include <winsock2.h> |
#elif defined(CONFIG_POSIX) |
typedef unsigned long InAddr; |
|
|
|
#else |
|
|
# include <unistd.h> | # include <unistd.h> |
# include <errno.h> | # include <errno.h> |
# include <sys/socket.h> | # include <sys/socket.h> |
|
|
# include <netdb.h> | # include <netdb.h> |
# include <fcntl.h> | # include <fcntl.h> |
# include <arpa/inet.h> | # include <arpa/inet.h> |
#endif |
|
|
|
#if defined(CONFIG_OS_WINDOWS) |
|
typedef unsigned long InAddr; |
|
#else |
|
typedef in_addr_t InAddr; | typedef in_addr_t InAddr; |
|
|
#endif | #endif |
| |
MI_Result Addr_Init( | MI_Result Addr_Init( |
Addr* self_, |
Addr* self, |
const char* host, | const char* host, |
unsigned short port) |
unsigned short port, |
|
MI_Boolean useSecondaryAddr) |
{ | { |
struct sockaddr_in* self = (struct sockaddr_in*)self_; |
#if defined CONFIG_OS_WINDOWS |
struct sockaddr_in* addr; |
|
| |
/* Clear address */ |
/* disabling IPv6 OACR warnings - D3M bug 52 */ |
memset((char*)self, 0, sizeof(*self)); |
|
addr = (struct sockaddr_in*)self; |
# ifdef _PREFAST_ |
|
# pragma prefast (push) |
|
# pragma prefast (disable: 24001) |
|
# pragma prefast (disable: 24002) |
|
# pragma prefast (disable: 38026) |
|
# endif |
|
struct sockaddr_in* sockaddr = (struct sockaddr_in*)self; |
| |
if (isalpha((unsigned char)host[0])) |
|
{ |
|
/* Handle host name */ | /* Handle host name */ |
struct hostent* p = gethostbyname((char*)host); |
const struct hostent* p = gethostbyname((char*)host); |
|
if (p == NULL) |
|
return MI_RESULT_FAILED; |
|
|
|
/* no support for IPv6 on Windows */ |
|
if (useSecondaryAddr) |
|
return MI_RESULT_FAILED; |
|
|
|
/* Clear address */ |
|
memset(self, 0, sizeof (Addr)); |
|
|
|
/* set up values */ |
|
sockaddr->sin_family = p->h_addrtype; |
|
self->is_ipv6 = MI_FALSE; |
|
self->sock_addr_size = sizeof (struct sockaddr_in); |
|
memcpy(&sockaddr->sin_addr, p->h_addr, p->h_length); |
|
|
|
/* Set the port */ |
|
sockaddr->sin_port = htons(port); |
|
self->port_high_endian = htons(port); |
|
return MI_RESULT_OK; |
|
|
|
# ifdef _PREFAST_ |
|
# pragma prefast (pop) |
|
# endif |
|
|
|
#else /* defined CONFIG_OS_WINDOWS */ |
|
|
|
struct addrinfo hints; |
|
struct addrinfo *addr_info, *rp; |
|
int error_no; |
|
|
|
/* set hints and get the primary address */ |
|
memset(&hints, 0, sizeof (struct addrinfo)); |
|
hints.ai_socktype = SOCK_STREAM; |
|
hints.ai_family = AF_UNSPEC; /* AF_UNSPEC means use preferred protocol */ |
|
error_no = getaddrinfo(host, NULL, &hints, &addr_info); |
|
if (error_no != 0) |
|
return MI_RESULT_FAILED; |
| |
if (!p) |
rp = addr_info; |
|
if (useSecondaryAddr && NULL != addr_info->ai_next) |
|
{ |
|
// Advance to the next entry in the chain |
|
rp = rp->ai_next; |
|
} |
|
else if (useSecondaryAddr) |
|
{ |
|
// No secondary address exists. |
return MI_RESULT_FAILED; | return MI_RESULT_FAILED; |
|
} |
| |
addr->sin_family = p->h_addrtype; |
if (rp->ai_family == AF_INET6) |
memcpy(&addr->sin_addr, p->h_addr, p->h_length); |
{ |
|
struct sockaddr_in6 * addr6 = (struct sockaddr_in6 *)(rp->ai_addr); |
|
// struct sockaddr_in6* addr6 = (struct sockaddr_in6*)(addr_info->ai_addr->sa_data - sizeof (unsigned short)); |
|
addr6->sin6_port = htons(port); |
} | } |
else | else |
{ | { |
/* Handle dotted notation */ |
struct sockaddr_in * addr4 = (struct sockaddr_in *)(rp->ai_addr); |
InAddr ip = inet_addr((char*)host); |
// struct sockaddr_in* addr4 = (struct sockaddr_in*)(addr_info->ai_addr->sa_data - sizeof (unsigned short)); |
|
addr4->sin_port = htons(port); |
|
} |
| |
if (ip == (InAddr)-1) |
memset(self->u.padding, 0, sizeof self->u.padding); |
return MI_RESULT_FAILED; |
memcpy(&self->u.sock_addr, rp->ai_addr, (size_t)rp->ai_addrlen); |
|
|
|
/* Set the duplicate copies of family, port and socket type */ |
|
self->sock_addr_size = rp->ai_addrlen; |
|
self->port_high_endian = htons(port); |
|
self->is_ipv6 = (rp->ai_family == AF_INET6); |
| |
addr->sin_addr.s_addr = ip; |
#if defined ENABLE_TRACING |
addr->sin_family = AF_INET; |
if (rp->ai_family == AF_INET6) |
|
{ |
|
struct sockaddr_in6* addr6 = (struct sockaddr_in6*)&self->u.sock_addr; |
|
fprintf(stderr, "Addr_Init - IPv6 address: %X:%X:%X:%X:%X:%X:%X:%X, port: %u\n", |
|
(unsigned int)ntohs(*(unsigned short*)&addr6->sin6_addr), |
|
(unsigned int)ntohs(*((unsigned short*)&addr6->sin6_addr + 1)), |
|
(unsigned int)ntohs(*((unsigned short*)&addr6->sin6_addr + 2)), |
|
(unsigned int)ntohs(*((unsigned short*)&addr6->sin6_addr + 3)), |
|
(unsigned int)ntohs(*((unsigned short*)&addr6->sin6_addr + 4)), |
|
(unsigned int)ntohs(*((unsigned short*)&addr6->sin6_addr + 5)), |
|
(unsigned int)ntohs(*((unsigned short*)&addr6->sin6_addr + 6)), |
|
(unsigned int)ntohs(*((unsigned short*)&addr6->sin6_addr + 7)), |
|
(unsigned int)ntohs(addr6->sin6_port)); |
} | } |
|
else |
|
{ |
|
struct sockaddr_in* addr4 = (struct sockaddr_in*)&self->u.sock_addr; |
| |
/* Set the port */ |
fprintf(stderr, "Addr_Init - IPv4 address: %u.%u.%u.%u, port: %u\n", |
self->sin_port = htons(port); |
(unsigned int)*((unsigned char*)&addr4->sin_addr.s_addr + 0), |
|
(unsigned int)*((unsigned char*)&addr4->sin_addr.s_addr + 1), |
|
(unsigned int)*((unsigned char*)&addr4->sin_addr.s_addr + 2), |
|
(unsigned int)*((unsigned char*)&addr4->sin_addr.s_addr + 3), |
|
(unsigned int)ntohs(addr4->sin_port)); |
|
} |
|
#endif /* defined(ENABLE_TRACING) */ |
|
freeaddrinfo(addr_info); |
return MI_RESULT_OK; | return MI_RESULT_OK; |
|
|
|
#endif /* defined CONFIG_OS_WINDOWS ... else */ |
} | } |
| |
void Addr_InitAny( | void Addr_InitAny( |
Addr* self_, |
Addr* self, |
unsigned short port) | unsigned short port) |
{ | { |
struct sockaddr_in* self = (struct sockaddr_in*)self_; |
#ifdef _PREFAST_ |
|
# pragma prefast (push) |
|
# pragma prefast (disable: 24002) |
|
#endif |
|
struct sockaddr_in* addr4; |
|
MI_Uint32 v4addr; |
| |
memset((char*)self, 0, sizeof(*self)); |
memset((char*)self, 0, sizeof (Addr)); |
self->sin_family = AF_INET; |
|
self->sin_addr.s_addr = htonl(INADDR_ANY); |
/* set the fields in the header */ |
self->sin_port = htons(port); |
self->sock_addr_size = (MI_Uint16)sizeof (struct sockaddr_in); |
|
self->port_high_endian = htons(port); |
|
self->is_ipv6 = MI_FALSE; |
|
|
|
/* set the fields in the bind address structure */ |
|
addr4 = (struct sockaddr_in*)&self->u.sock_addr; |
|
addr4->sin_family = AF_INET; |
|
addr4->sin_port = htons(port); |
|
v4addr = htonl(INADDR_ANY); |
|
memcpy(&addr4->sin_addr.s_addr, &v4addr, sizeof (MI_Uint32)); |
} | } |
|
|
|
#ifdef _PREFAST_ |
|
#pragma prefast (pop) |
|
#endif |