mirror of https://github.com/macssh/macssh.git
601 lines
13 KiB
C
Executable File
601 lines
13 KiB
C
Executable File
/*********************************************************************
|
|
Project : GUSI - Grand Unified Socket Interface
|
|
File : GUSIINETTest - Test unix domain sockets
|
|
Author : Matthias Neeracher <neeri@iis.ethz.ch>
|
|
Language : MPW C
|
|
|
|
$Log$
|
|
Revision 1.1.1.1 2001/03/03 21:49:39 chombier
|
|
Initial import
|
|
|
|
Revision 1.4 2000/10/15 21:49:20 neeri
|
|
Add multiple connection test
|
|
|
|
Revision 1.3 2000/05/23 06:40:03 neeri
|
|
Add Linger, Getsockname tests
|
|
|
|
Revision 1.2 2000/03/06 08:28:32 neeri
|
|
Releasing 2.0.5
|
|
|
|
Revision 1.1 1998/10/25 11:57:26 neeri
|
|
Ready to release 2.0a3
|
|
|
|
Revision 1.1 1994/12/31 00:50:27 neeri
|
|
Initial revision
|
|
|
|
Revision 0.6 1993/08/25 00:00:00 neeri
|
|
gethostbyaddr()
|
|
|
|
Revision 0.5 1993/07/29 00:00:00 neeri
|
|
servent tests
|
|
|
|
Revision 0.4 1993/03/03 00:00:00 neeri
|
|
Added performance test
|
|
|
|
Revision 0.3 1992/09/14 00:00:00 neeri
|
|
Misinterpreted hostent structure
|
|
|
|
Revision 0.2 1992/09/08 00:00:00 neeri
|
|
Factor out common socket routines
|
|
|
|
Revision 0.1 1992/09/08 00:00:00 neeri
|
|
First attempt
|
|
|
|
*********************************************************************/
|
|
|
|
#include "GUSITest.h"
|
|
#include <sys/types.h>
|
|
#include <netinet/in.h>
|
|
#include <netinet/tcp.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <sys/time.h>
|
|
#include <netdb.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
#include "Events.h"
|
|
|
|
char addrstr[100];
|
|
|
|
void Socket(char ch1, char ch2, const char * line)
|
|
{
|
|
sock = socket(AF_INET, (ch1 == 's') ? SOCK_STREAM : SOCK_DGRAM, 0);
|
|
|
|
if (sock == -1) {
|
|
printf("# socket() returned error %d [%s]\n", errno, Explain());
|
|
Where();
|
|
}
|
|
}
|
|
|
|
void Bind(char ch1, char ch2, const char * cmd)
|
|
{
|
|
int len;
|
|
struct sockaddr_in addr;
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
|
|
if (sscanf(cmd, "%s %hd", addrstr, &addr.sin_port) == 2) {
|
|
addr.sin_addr.s_addr = inet_addr(addrstr);
|
|
addr.sin_family = AF_INET;
|
|
len = sizeof(struct sockaddr_in);
|
|
} else {
|
|
Usage(ch1, ch2);
|
|
return;
|
|
}
|
|
|
|
if (bind(sock, (struct sockaddr *) &addr, len)) {
|
|
printf(
|
|
"bind(%s:%d) returned error %d [%s]\n",
|
|
inet_ntoa(addr.sin_addr),
|
|
addr.sin_port,
|
|
errno, Explain());
|
|
|
|
Where();
|
|
}
|
|
}
|
|
|
|
void NoDelay(char , char , const char * cmd)
|
|
{
|
|
int one = 1;
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
return;
|
|
}
|
|
|
|
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(int)))
|
|
printf(
|
|
"setsockopt(IPPROTO_TCP, TCP_NODELAY) returned error %d [%s]\n",
|
|
errno, Explain());
|
|
}
|
|
|
|
void Linger(char ch1, char ch2, const char * cmd)
|
|
{
|
|
struct linger l;
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
|
|
if (sscanf(cmd, "%d", &l.l_linger) == 1) {
|
|
l.l_onoff = l.l_linger > -1;
|
|
} else {
|
|
Usage(ch1, ch2);
|
|
return;
|
|
}
|
|
|
|
if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char*)&l, sizeof(struct linger)))
|
|
printf(
|
|
"setsockopt(SOL_SOCKET, SO_LINGER) returned error %d [%s]\n",
|
|
errno, Explain());
|
|
}
|
|
|
|
void Accept(char ch1, char ch2, const char * line)
|
|
{
|
|
socklen_t len;
|
|
struct sockaddr_in addr;
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
if (accsock != -1) {
|
|
printf("# can't accept more than one connection\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
|
|
len = sizeof(struct sockaddr_in);
|
|
sock = accept(accsock = sock, (struct sockaddr *) &addr, &len);
|
|
|
|
if (sock < 0) {
|
|
printf("# accept() returned error %d [%s]\n", errno, Explain());
|
|
sock = accsock;
|
|
accsock = -1;
|
|
} else {
|
|
printf(
|
|
"# accepted connection from %s port %d\n",
|
|
inet_ntoa(addr.sin_addr),
|
|
addr.sin_port);
|
|
}
|
|
|
|
Where();
|
|
}
|
|
|
|
void Getsockname(char ch1, char ch2, const char * line)
|
|
{
|
|
socklen_t len;
|
|
struct sockaddr_in addr;
|
|
int err;
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
|
|
len = sizeof(struct sockaddr_in);
|
|
|
|
if (ch2 == 's')
|
|
err = getsockname(accsock = sock, (struct sockaddr *) &addr, &len);
|
|
else
|
|
err = getpeername(accsock = sock, (struct sockaddr *) &addr, &len);
|
|
if (err < 0) {
|
|
printf("# get%sname() returned error %d [%s]\n",
|
|
(ch2 == 's' ? "sock" : "peer"), errno, Explain());
|
|
} else {
|
|
printf(
|
|
"# %s are %s port %d\n", (ch2 == 's' ? "We" : "They"),
|
|
inet_ntoa(addr.sin_addr),
|
|
addr.sin_port);
|
|
}
|
|
|
|
Where();
|
|
}
|
|
|
|
void Connect(char ch1, char ch2, const char * cmd)
|
|
{
|
|
int len;
|
|
struct sockaddr_in addr;
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
|
|
if (sscanf(cmd, "%s %hd", addrstr, &addr.sin_port) == 2) {
|
|
addr.sin_addr.s_addr = inet_addr(addrstr);
|
|
addr.sin_family = AF_INET;
|
|
len = sizeof(struct sockaddr_in);
|
|
} else {
|
|
Usage(ch1, ch2);
|
|
return;
|
|
}
|
|
|
|
if (connect(sock, (struct sockaddr *) &addr, len)) {
|
|
printf(
|
|
"connect(%s:%d) returned error %s\n",
|
|
inet_ntoa(addr.sin_addr),
|
|
addr.sin_port,
|
|
Explain());
|
|
Where();
|
|
}
|
|
}
|
|
|
|
static int sSock[1000];
|
|
static int sSockUsed;
|
|
|
|
void MultiConn(char ch1, char ch2, const char * cmd)
|
|
{
|
|
int len;
|
|
int count;
|
|
int i;
|
|
struct sockaddr_in addr;
|
|
|
|
if (sscanf(cmd, "%d %s %hd", &count, addrstr, &addr.sin_port) == 3) {
|
|
addr.sin_addr.s_addr = inet_addr(addrstr);
|
|
addr.sin_family = AF_INET;
|
|
len = sizeof(struct sockaddr_in);
|
|
} else {
|
|
Usage(ch1, ch2);
|
|
return;
|
|
}
|
|
|
|
if (count > 1000-sSockUsed)
|
|
count = 1000-sSockUsed;
|
|
for (i=0; i<count; ++i) {
|
|
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (connect(sock, (struct sockaddr *) &addr, len)) {
|
|
printf(
|
|
"#%d: connect(%s:%d) returned error %s\n",
|
|
i,
|
|
inet_ntoa(addr.sin_addr),
|
|
addr.sin_port,
|
|
Explain());
|
|
Where();
|
|
close(sock);
|
|
if (!i)
|
|
break;
|
|
} else {
|
|
struct sockaddr_in addr;
|
|
socklen_t len;
|
|
|
|
len = sizeof(struct sockaddr_in);
|
|
getsockname(sock, (struct sockaddr *) &addr, &len);
|
|
printf("#%d connected from port %d\n", i, addr.sin_port);
|
|
sSock[sSockUsed++] = sock;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MultiDis(char, char, const char * cmd)
|
|
{
|
|
while (sSockUsed > 0)
|
|
close(sSock[--sSockUsed]);
|
|
}
|
|
|
|
int ReadWhileUCan()
|
|
{
|
|
int res;
|
|
char * outline;
|
|
fd_set rdfds;
|
|
fd_set exfds;
|
|
struct timeval delay;
|
|
char out[500];
|
|
|
|
for (;;) {
|
|
FD_ZERO(&rdfds);
|
|
FD_ZERO(&exfds);
|
|
|
|
FD_SET(sock, &rdfds);
|
|
FD_SET(sock, &exfds);
|
|
|
|
delay.tv_sec = 1;
|
|
delay.tv_usec = 0;
|
|
|
|
res = select(sock+1, &rdfds, nil, &exfds, &delay);
|
|
|
|
if (res < 0) {
|
|
printf("# select() returned error %d [%s]\n", errno, Explain());
|
|
|
|
return -1;
|
|
} else if (!res)
|
|
return 0;
|
|
else if (res && FD_ISSET(sock, &exfds)) {
|
|
printf("# select() returned an exception\n");
|
|
|
|
return -1;
|
|
} else if (res && FD_ISSET(sock, &rdfds)) {
|
|
res = read(sock, out, 500);
|
|
|
|
if (res < 0) {
|
|
printf("# read() returned error %d [%s]\n", errno, Explain());
|
|
|
|
return -1;
|
|
}
|
|
|
|
out[res] = 0;
|
|
|
|
for (outline = strtok(out, "\n\r"); outline; outline = strtok(nil, "\n\r"))
|
|
printf("%s\n", outline);
|
|
}
|
|
}
|
|
}
|
|
|
|
void Telnet(char ch1, char ch2, const char * cmd)
|
|
{
|
|
int len;
|
|
int part;
|
|
int res;
|
|
char * line;
|
|
char * outline;
|
|
fd_set rdfds;
|
|
fd_set wrfds;
|
|
fd_set exfds;
|
|
struct timeval delay;
|
|
char in[100];
|
|
char out[500];
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
|
|
printf("# Entering Poor Man's Telnet mode\n");
|
|
|
|
for (;;) {
|
|
if (ReadWhileUCan())
|
|
break;
|
|
|
|
Prompt();
|
|
|
|
if (!fgets(in, 100, input))
|
|
break;
|
|
|
|
++inputline;
|
|
|
|
if (!strcmp(in, ".\n"))
|
|
break;
|
|
|
|
if (!strcmp(in, "?\n"))
|
|
continue;
|
|
|
|
len = strlen(in);
|
|
in[len++] = '\r';
|
|
in[len] = 0;
|
|
|
|
for (line = in; len; len -= part, line += part) {
|
|
part = 0;
|
|
|
|
FD_ZERO(&rdfds);
|
|
FD_ZERO(&wrfds);
|
|
FD_ZERO(&exfds);
|
|
|
|
FD_SET(sock, &rdfds);
|
|
FD_SET(sock, &wrfds);
|
|
FD_SET(sock, &exfds);
|
|
|
|
delay.tv_sec = 10;
|
|
delay.tv_usec = 0;
|
|
|
|
res = select(sock+1, &rdfds, &wrfds, &exfds, &delay);
|
|
|
|
if (res < 0) {
|
|
printf("# select() returned error %d [%s]\n", errno, Explain());
|
|
|
|
return;
|
|
} else if (!res) {
|
|
printf("# select() timed out\n");
|
|
|
|
return;
|
|
} else if (FD_ISSET(sock, &exfds)) {
|
|
printf("# select() returned an exception\n");
|
|
|
|
return;
|
|
}
|
|
|
|
if (FD_ISSET(sock, &rdfds)) {
|
|
res = read(sock, out, 500);
|
|
|
|
if (res < 0) {
|
|
printf("# read() returned error %d [%s]\n", errno, Explain());
|
|
|
|
return;
|
|
}
|
|
|
|
out[res] = 0;
|
|
|
|
for (outline = strtok(out, "\n\r"); outline; outline = strtok(nil, "\n\r"))
|
|
printf("%s\n", outline);
|
|
} else if (FD_ISSET(sock, &wrfds)) {
|
|
res = write(sock, line, len);
|
|
|
|
if (res < 0) {
|
|
line[strlen(line) - 2] = 0;
|
|
printf("# write(\"%s\") returned error %s\n", line, Explain());
|
|
|
|
return;
|
|
}
|
|
|
|
part = res;
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("# Leaving Poor Man's Telnet mode\n");
|
|
}
|
|
|
|
void N2Addr(char ch1, char ch2, const char * cmd)
|
|
{
|
|
struct in_addr addr;
|
|
struct hostent * ent;
|
|
|
|
if (sscanf(cmd, "%s", addrstr) == 1)
|
|
if (ent = gethostbyname(addrstr)) {
|
|
memcpy(&addr, ent->h_addr, sizeof(struct in_addr));
|
|
printf("# gethostbyname(%s) returned %s\n", addrstr, inet_ntoa(addr));
|
|
} else
|
|
printf("# gethostbyname(%s) failed.\n", addrstr);
|
|
else
|
|
Usage(ch1, ch2);
|
|
}
|
|
|
|
void A2Name(char ch1, char ch2, const char * cmd)
|
|
{
|
|
in_addr_t addr;
|
|
struct hostent * ent;
|
|
|
|
if (sscanf(cmd, "%s", addrstr) == 1) {
|
|
addr = inet_addr(addrstr);
|
|
if (ent = gethostbyaddr((char *) &addr, 0, 0)) {
|
|
printf("# gethostbyaddr(%s) returned %s\n", addrstr, ent->h_name);
|
|
} else
|
|
printf("# gethostbyaddr(%s) failed.\n", addrstr);
|
|
} else
|
|
Usage(ch1, ch2);
|
|
}
|
|
|
|
void PerfTest(char ch1, char ch2, const char * cmd)
|
|
{
|
|
int count;
|
|
int i;
|
|
long ticks;
|
|
char buf[1024];
|
|
|
|
if (sock == -1) {
|
|
printf("# socket is not open\n");
|
|
Where();
|
|
|
|
return;
|
|
}
|
|
|
|
if (sscanf(cmd, "%d", &count) == 1) {
|
|
ticks = TickCount();
|
|
for (i=0; i<count; i++) {
|
|
write(sock, buf, 1);
|
|
read(sock, buf, 1024);
|
|
}
|
|
printf("# Did %d iterations in %d ticks.\n", count, TickCount()-ticks);
|
|
} else
|
|
Usage(ch1, ch2);
|
|
}
|
|
|
|
void ServByName(char ch1, char ch2, const char * cmd)
|
|
{
|
|
struct servent * ent;
|
|
char proto[6];
|
|
|
|
if (sscanf(cmd, "%s %s", addrstr, proto) == 2)
|
|
if (ent = getservbyname(addrstr, proto))
|
|
printf("# getservbyname(%s %s) returned %d\n", addrstr, proto, ent->s_port);
|
|
else
|
|
printf("# getservbyname(%s %s) failed.\n", addrstr, proto);
|
|
else if (sscanf(cmd, "%s", addrstr) == 1)
|
|
if (ent = getservbyname(addrstr, NULL))
|
|
printf("# getservbyname(%s) returned %d\n", addrstr, ent->s_port);
|
|
else
|
|
printf("# getservbyname(%s) failed.\n", addrstr);
|
|
else
|
|
Usage(ch1, ch2);
|
|
}
|
|
|
|
void PrintServEnt(struct servent * ent, Boolean full)
|
|
{
|
|
char ** al;
|
|
|
|
printf("%s", ent->s_name);
|
|
|
|
if (full)
|
|
printf(" %d/%s", ent->s_port, ent->s_proto);
|
|
|
|
for (al = ent->s_aliases; *al; ++al)
|
|
printf(" %s", *al);
|
|
|
|
putchar('\n');
|
|
}
|
|
|
|
void ServByPort(char ch1, char ch2, const char * cmd)
|
|
{
|
|
int port;
|
|
struct servent * ent;
|
|
char proto[6];
|
|
|
|
if (sscanf(cmd, "%d %s", &port, proto) == 2)
|
|
if (ent = getservbyport(port, proto)) {
|
|
printf("# getservbyport(%d %s) returned ", port, proto);
|
|
|
|
PrintServEnt(ent, false);
|
|
} else
|
|
printf("# getservbyport(%d %s) failed.\n", addrstr, proto);
|
|
else if (sscanf(cmd, "%d %s", &port) == 1)
|
|
if (ent = getservbyport(port, NULL)) {
|
|
printf("# getservbyport(%d) returned ", port);
|
|
|
|
PrintServEnt(ent, false);
|
|
} else
|
|
printf("# getservbyport(%d) failed.\n", addrstr);
|
|
else
|
|
Usage(ch1, ch2);
|
|
}
|
|
|
|
void ServList(char ch1, char ch2, const char * line)
|
|
{
|
|
struct servent * ent;
|
|
|
|
setservent(0);
|
|
|
|
while (ent = getservent()) {
|
|
printf("# ");
|
|
PrintServEnt(ent, true);
|
|
}
|
|
}
|
|
|
|
main(int argc, char ** argv)
|
|
{
|
|
printf("GUSIINETTest MN 14May00\n\n");
|
|
|
|
COMMAND('s', 's', Socket, "", "Create a stream socket");
|
|
COMMAND('d', 's', Socket, "", "Create a datagram socket");
|
|
COMMAND('b', 'd', Bind, "addr port", "Bind to address");
|
|
COMMAND('c', 'o', Connect, "addr port", "Connect to address");
|
|
COMMAND('m', 'c', MultiConn, "# addr port", "Connect multiple times to address");
|
|
COMMAND('m', 'd', MultiDis, "", "Disconnect the connections");
|
|
COMMAND('a', 'c', Accept, "", "Accept a connection");
|
|
COMMAND('t', 'n', Telnet, "", "Play telnet");
|
|
COMMAND('n', 'a', N2Addr, "name", "Convert name to address");
|
|
COMMAND('a', 'n', A2Name, "addr", "Convert address to name");
|
|
COMMAND('p', 't', PerfTest,"count", "Do a performance test");
|
|
COMMAND('s', 'n', ServByName, "name", "Convert service name to port number");
|
|
COMMAND('s', 'p', ServByPort, "port", "Convert port number to service name");
|
|
COMMAND('s', 'l', ServList, "", "List services");
|
|
COMMAND('n', 'd', NoDelay, "", "Turn on NODELAY TCP option");
|
|
COMMAND('l', 'g', Linger, "", "Set LINGER socket option");
|
|
COMMAND('g', 's', Getsockname, "", "Get socket name");
|
|
COMMAND('g', 'p', Getsockname, "", "Get peer name");
|
|
|
|
AddSocketCommands();
|
|
|
|
RunTest(argc, argv);
|
|
CleanupSockets();
|
|
} |