// Sun, 18 Jun 2000
// Y.Takagi
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "Socket.h"
#include "SocketStream.h"
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
#include <errno.h>
Socket::Socket(const char *host, int port)
: __sock(-1), __is(NULL), __os(NULL), __error(false)
{
__host = host;
__port = port;
__localPort = -1;
__error_msg[0] = '\0';
open();
}
Socket::Socket(const char *host, int port, int localPort)
: __sock(-1), __is(NULL), __os(NULL), __error(false)
{
__host = host;
__port = port;
__localPort = localPort;
__error_msg[0] = '\0';
open();
}
Socket::~Socket()
{
close();
if (__is) {
delete __is;
}
if (__os) {
delete __os;
}
}
istream &Socket::getInputStream()
{
if (__is == NULL) {
__is = new isocketstream(this);
}
return *__is;
}
ostream &Socket::getOutputStream()
{
if (__os == NULL) {
__os = new osocketstream(this);
}
return *__os;
}
void Socket::open()
{
if (__sock == -1 && !__error) {
sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
unsigned long inaddr;
hostent *host_info;
if ((inaddr = inet_addr(__host.c_str())) != INADDR_NONE) {
memcpy(&sin.sin_addr, &inaddr, sizeof(inaddr));
sin.sin_family = AF_INET;
} else if ((host_info = gethostbyname(__host.c_str())) != NULL) {
memcpy(&sin.sin_addr, host_info->h_addr, host_info->h_length);
sin.sin_family = host_info->h_addrtype;
} else {
sprintf(__error_msg, "gethostbyname failed. errno = %d", errno);
__error = true;
return;
}
if ((__sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
sprintf(__error_msg, "socket failed. errno = %d", errno);
__error = true;
} else {
if (__localPort >= 0) {
sockaddr_in cin;
memset(&cin, 0, sizeof(cin));
cin.sin_family = AF_INET;
cin.sin_port = htons(__localPort);
if (::bind(__sock, (sockaddr *)&cin, sizeof(cin)) != 0) {
sprintf(__error_msg, "bind failed. errno = %d", errno);
::close(__sock);
__sock = -1;
__error = true;
}
}
sin.sin_port = htons(__port);
if (::connect(__sock, (sockaddr *)&(sin), sizeof(sin)) != 0) {
sprintf(__error_msg, "connect failed. errno = %d", errno);
::close(__sock);
__sock = -1;
__error = true;
}
}
}
}
void Socket::close()
{
if (__sock != -1) {
::shutdown(__sock, 2);
::close(__sock);
__sock = -1;
}
}
bool Socket::fail() const
{
return __sock == -1 || __error;
}
bool Socket::good() const
{
return !fail();
}
bool Socket::operator !() const
{
return fail();
}
int Socket::read(char *buffer, int size, int flags)
{
if (fail()) {
size = 0;
} else {
size = ::recv(__sock, buffer, size, flags);
if (size <= 0) {
sprintf(__error_msg, "recv failed. errno = %d", errno);
__error = true;
close();
}
}
return size;
}
int Socket::write(const char *buffer, int size, int flags)
{
if (fail()) {
size = 0;
} else {
size = ::send(__sock, buffer, size, flags);
if (size <= 0) {
sprintf(__error_msg, "send failed. errno = %d", errno);
__error = true;
close();
}
}
return size;
}
↑ V512 A call of the 'memcpy' function will lead to overflow of the buffer '& sin.sin_addr'.