зеркало из https://github.com/mozilla/pjs.git
304 строки
5.6 KiB
C
304 строки
5.6 KiB
C
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is Web Sniffer.
|
|
*
|
|
* The Initial Developer of the Original Code is Erik van der Poel.
|
|
* Portions created by Erik van der Poel are
|
|
* Copyright (C) 1998,1999,2000 Erik van der Poel.
|
|
* All Rights Reserved.
|
|
*
|
|
* Contributor(s): Bruce Robson
|
|
*/
|
|
|
|
#include "plat.h"
|
|
|
|
#include <errno.h>
|
|
#include <memory.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/types.h>
|
|
#ifdef PLAT_UNIX
|
|
#include <thread.h>
|
|
#include <sys/systeminfo.h>
|
|
#endif
|
|
#include <signal.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/wait.h>
|
|
|
|
#include "main.h"
|
|
#include "mutex.h"
|
|
#include "net.h"
|
|
#include "view.h"
|
|
|
|
static int connectCount = 0;
|
|
static int dnsCount = 0;
|
|
|
|
static char *
|
|
getHostName(void)
|
|
{
|
|
size_t alloc;
|
|
char *hostName;
|
|
#ifdef PLAT_UNIX
|
|
long size;
|
|
#endif
|
|
|
|
alloc = 512;
|
|
hostName = calloc(alloc, 1);
|
|
if (!hostName)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef PLAT_UNIX
|
|
while (1)
|
|
{
|
|
size = sysinfo(SI_HOSTNAME, hostName, alloc);
|
|
if (size < 0)
|
|
{
|
|
fprintf(stderr, "sysinfo failed\n");
|
|
return NULL;
|
|
}
|
|
else if (size > alloc)
|
|
{
|
|
alloc = size + 1;
|
|
hostName = realloc(hostName, alloc);
|
|
if (!hostName)
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
#else /* Windows */
|
|
if (gethostname(hostName, alloc) != 0)
|
|
{
|
|
fprintf(stderr, "gethostname failed\n");
|
|
free(hostName);
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
return hostName;
|
|
}
|
|
|
|
static int
|
|
getSocketAndIPAddress(void *a, unsigned char *hostName, int port,
|
|
struct sockaddr_in *addr)
|
|
{
|
|
#ifdef PLAT_UNIX
|
|
char buf[512];
|
|
int err;
|
|
#endif
|
|
struct hostent host;
|
|
struct hostent *ret;
|
|
unsigned short shortPort;
|
|
int sock;
|
|
struct timeval theTime;
|
|
|
|
sock = socket(PF_INET, SOCK_STREAM, 0);
|
|
if (sock < 0)
|
|
{
|
|
perror("socket failed");
|
|
return -1;
|
|
}
|
|
|
|
viewReport(a, "calling gethostbyname_r() on");
|
|
viewReport(a, (char *) hostName);
|
|
|
|
reportStatus(a, "gethostbyname_r", __FILE__, __LINE__);
|
|
|
|
gettimeofday(&theTime, NULL);
|
|
|
|
/* XXX implement my own DNS lookup to do timeouts? */
|
|
/* XXX implement my own DNS lookup to try again? */
|
|
#ifdef PLAT_UNIX
|
|
ret = gethostbyname_r((char *) hostName, &host, buf, sizeof(buf), &err);
|
|
if (!ret)
|
|
#else /* Windows */
|
|
ret = gethostbyname((char *) hostName);
|
|
if (ret != NULL)
|
|
{
|
|
host = *ret;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
reportTime(REPORT_TIME_GETHOSTBYNAME_FAILURE, &theTime);
|
|
reportStatus(a, "gethostbyname_r failed", __FILE__, __LINE__);
|
|
viewReport(a, "failed<br><hr>");
|
|
close(sock);
|
|
return -1;
|
|
}
|
|
|
|
reportTime(REPORT_TIME_GETHOSTBYNAME_SUCCESS, &theTime);
|
|
|
|
reportStatus(a, "gethostbyname_r succeeded", __FILE__, __LINE__);
|
|
|
|
viewReport(a, "succeeded<br><hr>");
|
|
|
|
MUTEX_LOCK();
|
|
dnsCount++;
|
|
MUTEX_UNLOCK();
|
|
memset(addr, 0, sizeof(*addr));
|
|
addr->sin_family = host.h_addrtype /* PF_INET */;
|
|
shortPort = port;
|
|
addr->sin_port = htons(shortPort);
|
|
memcpy(&addr->sin_addr, host.h_addr, host.h_length /* 4 */);
|
|
|
|
return sock;
|
|
}
|
|
|
|
int
|
|
netListen(void *a, unsigned char **host, u_short *port)
|
|
{
|
|
unsigned char *hostName;
|
|
struct sockaddr_in name;
|
|
int namelen = sizeof(name);
|
|
int fd;
|
|
|
|
hostName = (unsigned char *) getHostName();
|
|
if (!hostName)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fd = getSocketAndIPAddress(a, hostName, *port, &name);
|
|
if (fd < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
if (host)
|
|
{
|
|
*host = hostName;
|
|
}
|
|
else
|
|
{
|
|
free(hostName);
|
|
}
|
|
|
|
if (bind(fd, (struct sockaddr *) &name, sizeof(name)))
|
|
{
|
|
perror("bind");
|
|
return -1;
|
|
}
|
|
|
|
if (listen(fd, 5))
|
|
{
|
|
perror("listen");
|
|
return -1;
|
|
}
|
|
|
|
if (!*port)
|
|
{
|
|
if (getsockname(fd, (struct sockaddr *) &name, &namelen))
|
|
{
|
|
return -1;
|
|
}
|
|
*port = ntohs(name.sin_port);
|
|
}
|
|
|
|
return fd;
|
|
}
|
|
|
|
int
|
|
netAccept(int fd)
|
|
{
|
|
int newFD;
|
|
int addrlen = sizeof(struct sockaddr);
|
|
struct sockaddr addr;
|
|
|
|
while ((newFD = accept(fd, &addr, &addrlen)) < 0)
|
|
{
|
|
if (errno != EINTR)
|
|
{
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return newFD;
|
|
}
|
|
|
|
int
|
|
netConnect(void *a, unsigned char *hostName, int port)
|
|
{
|
|
struct sockaddr_in addr;
|
|
int sock;
|
|
struct timeval theTime;
|
|
|
|
sock = getSocketAndIPAddress(a, hostName, port, &addr);
|
|
if (sock < 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
viewReport(a, "calling connect()");
|
|
|
|
reportStatus(a, "connect", __FILE__, __LINE__);
|
|
|
|
gettimeofday(&theTime, NULL);
|
|
|
|
if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) == -1)
|
|
{
|
|
reportTime(REPORT_TIME_CONNECT_FAILURE, &theTime);
|
|
|
|
/* XXX try again if Connection timed out? */
|
|
/* XXX try again if Connection refused? */
|
|
if
|
|
(
|
|
(errno != ETIMEDOUT) &&
|
|
(errno != ECONNREFUSED)
|
|
)
|
|
{
|
|
fprintf(stderr, "cannot connect to %s at %d: ",
|
|
hostName, port);
|
|
perror(NULL);
|
|
}
|
|
close(sock);
|
|
reportStatus(a, "connect failed", __FILE__, __LINE__);
|
|
viewReport(a, "failed:");
|
|
viewReport(a, strerror(errno) ? strerror(errno) : "NULL");
|
|
viewReport(a, "<hr>");
|
|
return -1;
|
|
}
|
|
|
|
reportTime(REPORT_TIME_CONNECT_SUCCESS, &theTime);
|
|
|
|
reportStatus(a, "connect succeeded", __FILE__, __LINE__);
|
|
|
|
viewReport(a, "succeeded<br><hr>");
|
|
|
|
MUTEX_LOCK();
|
|
connectCount++;
|
|
MUTEX_UNLOCK();
|
|
|
|
return sock;
|
|
}
|
|
|
|
int
|
|
netGetConnectCount(void)
|
|
{
|
|
return connectCount;
|
|
}
|
|
|
|
int
|
|
netGetDNSCount(void)
|
|
{
|
|
return dnsCount;
|
|
}
|