/***************************************************************************
* DBS: Distributed Benchmark System
* Copyright (c) 1995, 1996, 1997 Yukio Murayama
* Copyright (c) 1995, 1996, 1997 Nara Institute of Science and Technology
* All rights reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided only with the following
* conditions are satisfied:
*
* 1. Both the copyright notice and this permission notice appear in
* all copies of the software, derivative works or modified versions,
* and any portions thereof, and that both notices appear in
* supporting documentation.
* 2. All advertising materials mentioning features or use of this
* software must display the following acknowledgement:
* This product includes software developed by Nara Institute of
* Science and Technology and its contributors.
* 3. Neither the name of Nara Institute of Science and Technology nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND NARA
* INSTITUTE OF SCIENCE AND TECHNOLOGY DISCLAIMS ANY LIABILITY OF
* ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF
* THIS SOFTWARE. ALSO, THERE IS NO WARRANTY IMPLIED OR OTHERWISE,
* NOR IS SUPPORT PROVIDED.
*
* Feedback of the results generated from any improvements or
* extensions made to this software would be much appreciated.
* Any such feedback should be sent to:
*
* Yukio Murayama
* E-mail: <yukio-m@is.aist-nara.ac.jp>
* URL: <http://shika.aist-nara.ac.jp/member/yukio-m/index.html>
* Address: Graduate School of Information Science,
* Nara Institute of Science and Technology,
* Takayama 8916-5, Ikoma, Nara, Japan
*
* Nara Institute of Science and Technology has the rights to
* redistribute these changes.
***************************************************************************/
/*****************************************************************
* Distributed Benchmark System
* Network Subroutines
* $Revision: 1.18 $
* $Date: 1997/07/11 00:54:07 $
* $Author: yukio-m $
*****************************************************************/
#ifdef __linux__
#include <endian.h>
#else
#if !defined(sun) && !defined(mips) && !defined(ultrix) && !defined(__hpux)
#include <machine/endian.h>
#endif
#endif
/*#define _SOCKADDR_LEN*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <errno.h>
#include "dbs.h"
#include "dbsd.h"
#define ASSOSIATION_DEBUG {\
int sp, dp, sa, da;\
sa=(int)ntohl(a->source_address);\
sp=(int)ntohs(a->source_port);\
da=(int)ntohl(a->dest_address);\
dp=(int)ntohs(a->dest_port);\
fprintf(stderr,"ASSOSIATION:(%3d.%3d.%3d.%3d, %3d.%3d.%3d.%3d)(%5d,%5d)\n",\
GET_IP_ADDR(sa,4), GET_IP_ADDR(sa,3), GET_IP_ADDR(sa,2), GET_IP_ADDR(sa,1),\
GET_IP_ADDR(da,4), GET_IP_ADDR(da,3), GET_IP_ADDR(da,2), GET_IP_ADDR(da,1),\
sp,dp);\
}
void getaddr_sub __P((char *hostname, int port, struct sockaddr_in *address));
void socket_opt __P((int fd, struct dbsd_param *cmd));
/****************************************************************
* Address resolution Subroutine
****************************************************************/
/*
* Get Address Subroutine
*
* {hostname, port} -> (struct sockaddr_in *)address
*/
void getaddr_sub(hostname, port, address)
char *hostname;
int port;
struct sockaddr_in *address;
{
unsigned int tmp;
struct hostent *hp;
#ifndef INADDR_NONE
#define INADDR_NONE (-1)
#endif
address->sin_family = AF_INET;
address->sin_port = htons((short)port);
if (strcmp(hostname,"") == 0) {
address->sin_addr.s_addr = htonl(INADDR_ANY);
} else {
tmp = inet_addr(hostname);
if(tmp != (unsigned long) INADDR_NONE){
address->sin_addr.s_addr = tmp;
} else {
if ((hp = gethostbyname(hostname)) == NULL) {
char tmp[512];
sprintf(tmp, "gethostbyname \"%s\"", hostname);
DEBUGMSG2(1, perror("gethostbyname"));
safe_exit(GETHOSTBYNAME, tmp, strerror(errno));
}
bcopy((char *)hp->h_addr, (char *)&address->sin_addr, hp->h_length);
}
}
}
/*
* Get Address Subroutine
*
* Set (struct sockaddr_in *)address
*/
void getaddr(a, d_address, b_address)
struct assosiation *a;
struct sockaddr_in *d_address;
struct sockaddr_in *b_address;
{
bzero((char *)d_address, sizeof(*d_address));
bzero((char *)b_address, sizeof(*b_address));
getaddr_sub(a->dsthostname, (int)a->dest_port, d_address);
getaddr_sub(a->srchostname, (int)a->source_port, b_address);
}
/*
* Set Address
*
* File Descripter -> (struct assosiation *)
*/
void setaddr(fd, a)
int fd;
struct assosiation *a;
{
struct sockaddr_in dest;
struct sockaddr_in source;
int len;
len = sizeof (dest);
getpeername(fd, (struct sockaddr *) &dest, &len);
len = sizeof (source);
getsockname(fd, (struct sockaddr *) &source, &len);
a->source_address = source.sin_addr.s_addr;
a->source_port = source.sin_port;
a->dest_address = dest.sin_addr.s_addr;
a->dest_port = dest.sin_port;
DEBUGMSG2(5, ASSOSIATION_DEBUG);
}
/*****************************************************************
* TCP Initialization Server
*
* Return Value: file descripter
*****************************************************************/
int tcp_init_server(a, cmd)
struct assosiation *a;
struct dbsd_param *cmd;
{
getaddr(a, &cmd->d_address, &cmd->b_address);
if ((cmd->sockfd = socket(cmd->d_address.sin_family, SOCK_STREAM, 0)) <0)
safe_exit(SOCKET, "TCP SERVER socket", strerror(errno));
if (bind(cmd->sockfd, (struct sockaddr *)&cmd->b_address, sizeof(cmd->b_address)) < 0)
safe_exit(BIND, "TCP SERVER bind", strerror(errno));
socket_opt(cmd->sockfd, cmd);
listen(cmd->sockfd, 1);
return 0;
}
/*
* TCP Initialization Server2
*
* Connection_mode == BEFORE
*/
int tcp_init_server2(a, cmd)
struct assosiation *a;
struct dbsd_param *cmd;
{
if (cmd->connection_mode == BEFORE) {
int d_len = sizeof(cmd->d_address);
DEBUGMSG2(2, fprintf(stderr, "Wait Connection from (%s).(%d).....",
a->dsthostname, (int)ntohs(cmd->d_address.sin_port)));
if ((cmd->fd = accept(cmd->sockfd, (struct sockaddr *)&cmd->d_address, &d_len)) < 0)
safe_exit(ACCEPT, "TCP SERVER accept", strerror(errno));
DEBUGMSG(2, "Accepted.\n");
setaddr(cmd->fd, a);
close(cmd->sockfd);
return cmd->fd;
}
return 0;
}
/*****************************************************************
* TCP Initialization Client
*
* Return Value: file descripter
*****************************************************************/
int tcp_init_client(a, cmd)
struct assosiation *a;
struct dbsd_param *cmd;
{
DEBUGMSG(2, "TCP_INIT_CLIENT: ");
getaddr(a, &cmd->d_address, &cmd->b_address);
if ((cmd->fd = socket(cmd->d_address.sin_family, SOCK_STREAM, 0)) <0)
safe_exit(SOCKET, "TCP CLIENT socket", strerror(errno));
if (bind(cmd->fd, (struct sockaddr *)&cmd->b_address, sizeof(cmd->b_address)) < 0)
safe_exit(BIND, "TCP CLIENT bind", strerror(errno));
socket_opt(cmd->fd, cmd);
if (cmd->connection_mode == BEFORE) {
DEBUGMSG2(2, fprintf(stderr, "Connecting to (%s).(%u).....",
a->dsthostname, (int)ntohs(cmd->d_address.sin_port)));
if (connect(cmd->fd, (struct sockaddr *)&cmd->d_address, sizeof(cmd->d_address)) < 0)
safe_exit(CONNECT, "TCP CLIENT connect", strerror(errno));
DEBUGMSG(2, "Connected.\n");
setaddr(cmd->fd, a);
return cmd->fd;
}
return 0;
}
/*****************************************************************
* UDP Initialization
*****************************************************************/
int udp_init(a, cmd)
struct assosiation *a;
struct dbsd_param *cmd;
{
DEBUGMSG(2, "TCP_INIT_SERVER:\n");
getaddr(a, &cmd->d_address, &cmd->b_address);
if ((cmd->fd = socket(cmd->d_address.sin_family, SOCK_DGRAM, 0)) < 0)
safe_exit(SOCKET, "UDP Socket Open", strerror(errno));
if (bind(cmd->fd, (struct sockaddr *)&cmd->b_address, sizeof(cmd->b_address)) < 0)
safe_exit(BIND, "UDP Bind Socket(Server)", strerror(errno));
socket_opt(cmd->fd, cmd);
return cmd->fd;
}
/*****************************************************************
* Set Socket Option
*****************************************************************/
void socket_opt(fd, cmd)
int fd;
struct dbsd_param *cmd;
{
int i;
i = cmd->sock_opt.send_buff;
if (i > 0) {
DEBUGMSG2(2, fprintf(stderr, " send_buff = %dbyte\n", i));
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&i, sizeof(i)) < 0)
safe_exit(SOSNDBUF, "setsockopt", strerror(errno));
}
i = cmd->sock_opt.recv_buff;
if (i > 0) {
DEBUGMSG2(2, fprintf(stderr, " recv_buff = %dbyte\n", i));
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&i, sizeof(i)) < 0)
safe_exit(SORCVBUF, "setsockopt", strerror(errno));
}
i = cmd->sock_opt.so_debug;
if (i == ON) {
DEBUGMSG2(2, fprintf(stderr, " so_debug = %s\n", (i==ON)?"ON":"OFF"));
if (setsockopt(fd, SOL_SOCKET, SO_DEBUG, (char *)&i, sizeof(i)) < 0)
safe_exit(SODEBUG, "setsockopt", strerror(errno));
}
i = cmd->sock_opt.no_delay;
if (i == ON) {
DEBUGMSG2(2, fprintf(stderr, " tcp_nodelay = %s\n", (i==ON)?"ON":"OFF"));
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&i, sizeof(i)) < 0)
safe_exit(TCPNODELAY, "setsockopt", strerror(errno));
}
i = cmd->sock_opt.mss;
if (i > 0) {
DEBUGMSG2(2, fprintf(stderr, " mss = %dbyte\n", i));
if (setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (char *)&i, sizeof(i)) < 0)
safe_exit(TCPMAXSEG, "setsockopt", strerror(errno));
}
if (cmd->assosiation.transport == TCP) {
int l = sizeof(i);
if (getsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, (char *)&i, &l) < 0)
safe_exit(ABNORMAL, "getsockopt", strerror(errno));
cmd->sock_opt.mss = i;
l = sizeof(i);
if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&i, &l) < 0)
safe_exit(ABNORMAL, "getsockopt", strerror(errno));
cmd->sock_opt.send_buff = i;
l = sizeof(i);
if (getsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&i, &l) < 0)
safe_exit(ABNORMAL, "getsockopt", strerror(errno));
cmd->sock_opt.recv_buff = i;
DEBUGMSG2(2, fprintf(stderr, " MSS=%d SNDBUF=%d RCVBUF=%d\n",
cmd->sock_opt.mss, cmd->sock_opt.send_buff, cmd->sock_opt.recv_buff));
}
}
syntax highlighted by Code2HTML, v. 0.9.1