2010-03-08 04:55:21 -06:00
|
|
|
/*****************************************************************************
|
|
|
|
*
|
|
|
|
* NCSA DTM version 2.3
|
|
|
|
* May 1, 1992
|
|
|
|
*
|
|
|
|
* NCSA DTM Version 2.3 source code and documentation are in the public
|
|
|
|
* domain. Specifically, we give to the public domain all rights for future
|
|
|
|
* licensing of the source code, all resale rights, and all publishing rights.
|
|
|
|
*
|
|
|
|
* We ask, but do not require, that the following message be included in all
|
|
|
|
* derived works:
|
|
|
|
*
|
|
|
|
* Portions developed at the National Center for Supercomputing Applications at
|
|
|
|
* the University of Illinois at Urbana-Champaign.
|
|
|
|
*
|
|
|
|
* THE UNIVERSITY OF ILLINOIS GIVES NO WARRANTY, EXPRESSED OR IMPLIED, FOR THE
|
|
|
|
* SOFTWARE AND/OR DOCUMENTATION PROVIDED, INCLUDING, WITHOUT LIMITATION,
|
|
|
|
* WARRANTY OF MERCHANTABILITY AND WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
*
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
**
|
|
|
|
** $Header: /X11/mosaic/cvsroot/xmosaic3/libdtm/socket.c,v 1.2 1995/10/13 06:33:27 spowers Exp $
|
|
|
|
**
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* $Log: socket.c,v $
|
|
|
|
* Revision 1.2 1995/10/13 06:33:27 spowers
|
|
|
|
* Solaris support added.
|
|
|
|
*
|
|
|
|
* Revision 1.1.1.1 1995/01/11 00:03:03 alanb
|
|
|
|
* New CVS source tree, Mosaic 2.5 beta 4
|
|
|
|
*
|
|
|
|
* Revision 2.5 1994/12/29 23:40:27 alanb
|
|
|
|
* I'm committing with a new symbolic revision number.
|
|
|
|
*
|
|
|
|
* Revision 1.1.1.1 1994/12/28 21:37:34 alanb
|
|
|
|
*
|
|
|
|
* Revision 1.3 1993/10/29 03:46:50 marca
|
|
|
|
* Tweaks.
|
|
|
|
*
|
|
|
|
* Revision 1.2 1993/10/06 06:19:10 ebina
|
|
|
|
* Ditto const shit
|
|
|
|
*
|
|
|
|
* Revision 1.1.1.1 1993/07/04 00:03:14 marca
|
|
|
|
* Mosaic for X version 2 distribution
|
|
|
|
*
|
|
|
|
* Revision 1.1 1993/01/18 21:50:44 marca
|
|
|
|
* I think I got it now.
|
|
|
|
*
|
|
|
|
* Revision 1.28 92/04/30 20:25:27 jplevyak
|
|
|
|
* Changed Version to 2.3.
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* Revision 1.27 1992/04/06 15:58:49 jplevyak
|
|
|
|
* Fixed minor problems for machines little Endian machines.
|
|
|
|
*
|
|
|
|
* Revision 1.26 92/03/10 22:07:10 jplevyak
|
|
|
|
* Added changed for PC/MAC from Quincey Koziol (koziol@ncsa.uiuc.edu)
|
|
|
|
* with modification.
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* Revision 1.25 1992/02/28 03:40:24 jplevyak
|
|
|
|
* int/long confict fix (no diff on workstations)
|
|
|
|
* ,
|
|
|
|
*
|
|
|
|
* Revision 1.24 92/01/30 19:33:07 jplevyak
|
|
|
|
* Fix bug in MAC version of dtm_get_ipaddr.
|
|
|
|
*
|
|
|
|
* Revision 1.23 1992/01/15 17:05:37 creiman
|
|
|
|
* Added typecast to dtm_socket_init:getsockname
|
|
|
|
*
|
|
|
|
* Revision 1.22 1992/01/14 16:31:40 creiman
|
|
|
|
* Removed mac #include
|
|
|
|
*
|
|
|
|
* Revision 1.21 1991/12/17 23:46:30 jefft
|
|
|
|
* dtm_socket_init used to only determine the socketname for logical ports,
|
|
|
|
* it now correctly sets the sockaddr_in structure maintained within the DTM
|
|
|
|
* port structure for every call.
|
|
|
|
*
|
|
|
|
* Revision 1.20 1991/10/29 22:07:10 sreedhar
|
|
|
|
* struct sockaddr * type casting
|
|
|
|
*
|
|
|
|
* Revision 1.19 1991/10/29 16:38:58 jplevyak
|
|
|
|
* Fixed bug in code that parses addressses. (extra (STDINT)).
|
|
|
|
*
|
|
|
|
* Revision 1.18 1991/10/16 23:26:00 jplevyak
|
|
|
|
* Fixed debugging message.
|
|
|
|
*
|
|
|
|
* Revision 1.17 1991/10/15 18:21:25 jplevyak
|
|
|
|
* Changed memcpy to structure cast, select field and assign. This
|
|
|
|
* is less kludgy and not only that, it works on the CRAY which the other
|
|
|
|
* did not.
|
|
|
|
*
|
|
|
|
* Revision 1.16 1991/10/14 16:49:32 jplevyak
|
|
|
|
* Fix problem with physical addressing.
|
|
|
|
*
|
|
|
|
* Revision 1.15 1991/10/10 15:15:04 jplevyak
|
|
|
|
* Fixed naming convensions.
|
|
|
|
*
|
|
|
|
* Revision 1.14 91/09/26 20:21:55 jplevyak
|
|
|
|
* Cosmetics
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* Revision 1.13 91/09/18 15:33:08 jplevyak
|
|
|
|
* Added additional parameter to dtm_socket_init
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* Revision 1.12 91/09/13 20:28:52 sreedhar
|
|
|
|
* accept :9900 change
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* Revision 1.11 1991/09/13 20:13:35 sreedhar
|
|
|
|
* take current host as default
|
|
|
|
*
|
|
|
|
* Revision 1.10 1991/08/19 18:53:37 jefft
|
|
|
|
* Fixed bug with dtm_socket_init, now checks port number for absolute
|
|
|
|
* address instead of the IP address (which isn't used anyway).
|
|
|
|
*
|
|
|
|
* Revision 1.9 1991/08/15 18:56:35 sreedhar
|
|
|
|
* Changes for logical portname version
|
|
|
|
*
|
|
|
|
* Revision 1.7 1991/06/11 15:19:45 sreedhar
|
|
|
|
* disclaimer added
|
|
|
|
*
|
|
|
|
* Revision 1.6 1991/06/07 16:07:21 sreedhar
|
|
|
|
* Changes for sequence start message
|
|
|
|
*
|
|
|
|
* Revision 1.5 1991/05/30 15:52:10 sreedhar
|
|
|
|
* Changes for readMsg/writeMsg internal release
|
|
|
|
*
|
|
|
|
* Revision 1.4 1990/12/11 14:11:38 jefft
|
|
|
|
* made dtm_get_ipaddr CRAY specific to fix final portability problem.
|
|
|
|
*
|
|
|
|
* Revision 1.3 90/11/21 12:43:15 jefft
|
|
|
|
* Fixed portibility problem with dtm_get_ipaddr.
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* Revision 1.2 90/11/21 10:54:18 jefft
|
|
|
|
* Added new routine, dtm_get_ipaddr. It returns an ascii string of the
|
|
|
|
* current hosts IP address.
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
* Revision 1.1 90/11/08 16:39:40 jefft
|
|
|
|
* Initial revision
|
2013-03-09 18:59:42 -06:00
|
|
|
*
|
2010-03-08 04:55:21 -06:00
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
+++++ System call - merge dtm_connect, dtm_quick_connect +++++
|
|
|
|
|
|
|
|
Check on whether dtm_get_ipaddr and dtm_init_sockaddr can be merged.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#ifdef _ARCH_MSDOS
|
|
|
|
#include <io.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <nmpcip.h>
|
|
|
|
#include "uio.h"
|
|
|
|
#else
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/* Machine specific header file(s) */
|
|
|
|
|
|
|
|
#ifdef SOLARIS
|
|
|
|
#include <sys/filio.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef RS6000
|
|
|
|
#include <sys/select.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _ARCH_MSDOS
|
|
|
|
#include <nmpcip.h>
|
|
|
|
#else
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#endif
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "dtmint.h"
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int buf_size = DTM_BUFF_SIZE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
dtm_parse_ipaddr()
|
|
|
|
Check whetherer given address string is in dotted
|
2013-03-09 18:59:42 -06:00
|
|
|
decimal notation and if so, to return the address in network byte
|
2010-03-08 04:55:21 -06:00
|
|
|
order.
|
|
|
|
|
|
|
|
Return values : TRUE, if in dotted decimal notation.
|
|
|
|
( network order address returned thru *addr )
|
|
|
|
FALSE, if not.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_parse_ipaddr(char *s,unsigned long *addr )
|
|
|
|
#else
|
|
|
|
int dtm_parse_ipaddr( s, addr )
|
|
|
|
char *s; /* address string */
|
|
|
|
unsigned long *addr; /* location to return network byte order address */
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int b1, b2, b3, b4;
|
|
|
|
int got;
|
|
|
|
|
|
|
|
if( (got = sscanf(s, "%d.%d.%d.%d", &b1, &b2, &b3, &b4)) != 4 ) {
|
|
|
|
DTMerrno = DTMADDR;
|
|
|
|
return DTMERROR;
|
|
|
|
}
|
|
|
|
*addr = htonl(b1 << 24 | b2 << 16 | b3 << 8 | b4);
|
|
|
|
return DTM_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
dtm_quick_select()
|
|
|
|
Check whether a socket (s) has count bytes ready.
|
|
|
|
*/
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_quick_select(int s,int *count)
|
|
|
|
#else
|
|
|
|
int dtm_quick_select(s, count)
|
|
|
|
int s;
|
|
|
|
int *count;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
fd_set filedes;
|
|
|
|
static struct timeval timeout = {0L, 0L};
|
|
|
|
|
|
|
|
DBGFLOW("# dtm_quick_select called.\n");
|
|
|
|
|
|
|
|
FD_ZERO(&filedes);
|
|
|
|
FD_SET(s, &filedes);
|
|
|
|
|
|
|
|
#ifdef __hpux
|
|
|
|
if (select(32, (int *)&filedes, (int *)NULL, (int *)NULL, &timeout)) {
|
|
|
|
#else
|
|
|
|
if (select(32, &filedes, (fd_set *)NULL, (fd_set *)NULL, &timeout)) {
|
|
|
|
#endif
|
|
|
|
ioctl(s, FIONREAD, count);
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
*count = 0;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
dtm_select()
|
|
|
|
Wait (time) seconds for count bytes to be ready on socket s.
|
|
|
|
*/
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_select(int s,int32 *count,int32 time )
|
|
|
|
#else
|
|
|
|
int dtm_select( s, count, time )
|
|
|
|
int s;
|
|
|
|
int32 *count;
|
|
|
|
int32 time;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
fd_set filedes;
|
|
|
|
static struct timeval timeout = { 0L, 0L };
|
|
|
|
|
|
|
|
DBGFLOW("# dtm_select called.\n");
|
|
|
|
|
|
|
|
timeout.tv_sec = time ;
|
|
|
|
|
|
|
|
FD_ZERO( &filedes );
|
|
|
|
FD_SET( s, &filedes );
|
|
|
|
|
|
|
|
#ifdef __hpux
|
2013-03-09 18:59:42 -06:00
|
|
|
if( (*count = select( 32, (int *)&filedes, (int *)NULL, (int *)NULL,
|
2010-03-08 04:55:21 -06:00
|
|
|
#else
|
2013-03-09 18:59:42 -06:00
|
|
|
if( (*count = select( 32, &filedes, (fd_set *)NULL, (fd_set *)NULL,
|
2010-03-08 04:55:21 -06:00
|
|
|
#endif
|
|
|
|
&timeout ) )) {
|
|
|
|
ioctl( s, FIONREAD, count );
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
dtm_accept().
|
|
|
|
Function to accept connection request on specified socket.
|
|
|
|
*/
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_accept(int s,S_ADDR *sn,struct timeval *timeout )
|
|
|
|
#else
|
|
|
|
int dtm_accept( s, sn, timeout )
|
|
|
|
int s;
|
|
|
|
S_ADDR *sn;
|
|
|
|
struct timeval *timeout ;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int snsize = sizeof (S_ADDR);
|
|
|
|
|
|
|
|
DBGFLOW( "dtm_accept called.\n");
|
|
|
|
DBGMSG1( "dtm_accept: sockfd = %d\n", s );
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/*
|
|
|
|
Await connect for specified time period only.
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
if timeout == NULL, it means just goahead and accept,
|
|
|
|
else wait for specified period and accept only if
|
|
|
|
connection request arrives in that period.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ( timeout ) {
|
2013-03-09 18:59:42 -06:00
|
|
|
fd_set readmask ;
|
2010-03-08 04:55:21 -06:00
|
|
|
fd_set *fchk = &readmask ;
|
|
|
|
int nf ;
|
|
|
|
|
|
|
|
FD_ZERO( fchk );
|
2013-03-09 18:59:42 -06:00
|
|
|
FD_SET( s, fchk );
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
#ifdef __hpux
|
|
|
|
nf = select( FD_SETSIZE, (int *)fchk, (int *)0, (int *)0, timeout );
|
|
|
|
#else
|
|
|
|
nf = select( FD_SETSIZE, fchk, (fd_set *)0, (fd_set *)0, timeout );
|
|
|
|
#endif
|
|
|
|
if ( nf < 0 ) {
|
|
|
|
DBGINT( "dtm_accept: select errno %d\n", errno );
|
|
|
|
DTMerrno = DTMSELECT ;
|
|
|
|
return DTMERROR ;
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
if ( nf == 0 ) {
|
|
|
|
/* No connect request in specified time */
|
|
|
|
|
|
|
|
DBGFLOW( "dtm_accept: timed out\n" );
|
|
|
|
return DTMERROR ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* accept connections on socket */
|
|
|
|
|
|
|
|
if ((s = accept(s, (struct sockaddr *)sn, &snsize)) < 0 ) {
|
|
|
|
DTMerrno = DTMSOCK;
|
|
|
|
DBGINT("dtm_accept: error %d accepting connection.", errno );
|
|
|
|
return DTMERROR ;
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
dtm_connect()
|
|
|
|
Attempt to connect to the the address sn, returning
|
|
|
|
the connected port in *s.
|
|
|
|
returns DTMERROR on failure. DTM_OK on success.
|
|
|
|
*/
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_connect(S_ADDR *sn,int *s)
|
|
|
|
#else
|
|
|
|
int dtm_connect(sn, s)
|
|
|
|
S_ADDR *sn;
|
|
|
|
int *s;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int d;
|
|
|
|
int refusedcount = 0;
|
|
|
|
|
|
|
|
DBGFLOW("dtm_connect called.\n");
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_connect: s_addr = %x\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohl( sn -> sin_addr.s_addr ) );
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_connect: sin_port = %d\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohs( sn -> sin_port ));
|
|
|
|
|
|
|
|
while (TRUE) {
|
|
|
|
|
|
|
|
/* create socket */
|
|
|
|
if ((d = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
|
|
DTMerrno = DTMSOCK;
|
|
|
|
DTMERR("dtm_connect: could not create socket.");
|
|
|
|
return DTMERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* attempt to connect to receiver */
|
|
|
|
if (connect(d, (struct sockaddr *)sn, sizeof (S_ADDR)) < 0) {
|
|
|
|
/* if connection refused, try again in 2 second */
|
|
|
|
if (errno == ECONNREFUSED) {
|
|
|
|
close(d);
|
|
|
|
sleep(2);
|
|
|
|
if ((refusedcount += 1) > DTM_REFUSE_LIMIT) {
|
|
|
|
DTMerrno = DTMTIMEOUT;
|
|
|
|
return DTMERROR;
|
|
|
|
} else
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
/* system error, can not connect, quit */
|
|
|
|
DTMerrno = DTMSOCK;
|
|
|
|
DTMERR("dtm_connect: could not connect.");
|
|
|
|
return DTMERROR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* connect complete, set working socket to original socket */
|
|
|
|
*s = d;
|
|
|
|
setsockopt(*s, IPPROTO_TCP, TCP_NODELAY, (char *)&d, sizeof d);
|
2013-03-09 18:59:42 -06:00
|
|
|
setsockopt(*s, SOL_SOCKET, SO_SNDBUF, (char *)&buf_size,
|
2010-03-08 04:55:21 -06:00
|
|
|
sizeof(int));
|
|
|
|
return DTM_OK;
|
|
|
|
}
|
|
|
|
} /* end while */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
dtm_quick_connect()
|
|
|
|
*/
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_quick_connect(S_ADDR *sn,int *s)
|
|
|
|
#else
|
|
|
|
int dtm_quick_connect(sn, s)
|
|
|
|
S_ADDR *sn;
|
|
|
|
int *s;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int d;
|
|
|
|
|
|
|
|
DBGFLOW("# dtm_quick_connect called.\n");
|
|
|
|
|
|
|
|
/* create socket */
|
|
|
|
if ((d = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
|
|
DTMerrno = DTMSOCK;
|
|
|
|
DBGFLOW("dtm_quick_connect: could not create socket.");
|
|
|
|
return DTMERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* attempt to connect to receiver */
|
|
|
|
if (connect(d, (struct sockaddr *)sn, sizeof (S_ADDR)) < 0) {
|
|
|
|
|
|
|
|
/* if connection refused */
|
|
|
|
|
|
|
|
if (errno == ECONNREFUSED) {
|
|
|
|
close(d);
|
|
|
|
DTMerrno = DTMTIMEOUT;
|
|
|
|
return DTMERROR;
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* system error, can not connect, quit */
|
|
|
|
|
|
|
|
DTMerrno = DTMSOCK;
|
|
|
|
DBGFLOW("dtm_quick_connect: could not connect.");
|
|
|
|
return DTMERROR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
/* else connection has been made */
|
|
|
|
|
|
|
|
*s = d;
|
|
|
|
setsockopt(*s, IPPROTO_TCP, TCP_NODELAY, (char *)&d, sizeof d);
|
|
|
|
setsockopt(*s, SOL_SOCKET, SO_SNDBUF, (char *)&buf_size, sizeof (int));
|
|
|
|
return DTM_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_end_connect(int s)
|
|
|
|
#else
|
|
|
|
int dtm_end_connect(s)
|
|
|
|
int s;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
|
|
|
|
struct linger lbuf ;
|
|
|
|
|
|
|
|
DBGFLOW("# dtm_end_connect called.\n");
|
|
|
|
DBGINT( "dtm_end_connect: sockfd %d\n", s );
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
lbuf.l_onoff = 0 ;
|
|
|
|
setsockopt( s, SOL_SOCKET, SO_LINGER, &lbuf, sizeof( struct linger ) );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return close( s );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
2013-03-09 18:59:42 -06:00
|
|
|
Return values :
|
2010-03-08 04:55:21 -06:00
|
|
|
On success,
|
|
|
|
Direct - host address in network byte order.
|
2013-03-09 18:59:42 -06:00
|
|
|
Indirect - *ipaddr has host address in dotted
|
|
|
|
decimal notation.
|
2010-03-08 04:55:21 -06:00
|
|
|
|
|
|
|
On error, 0.
|
|
|
|
Notes:
|
|
|
|
Error is returned as 0, since an internet address
|
|
|
|
of 0 is not possible for any host ( 0 refers to 'this' host
|
|
|
|
in internet context ).
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
unsigned long dtm_get_ipaddr(char *ipaddrstr )
|
|
|
|
#else
|
|
|
|
unsigned long dtm_get_ipaddr( ipaddrstr )
|
|
|
|
char *ipaddrstr ;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
char hostname[MAXHOSTNAMELEN];
|
|
|
|
struct hostent *hp;
|
|
|
|
unsigned long tmp;
|
|
|
|
|
|
|
|
DBGFLOW( "dtm_get_ipaddr called\n" );
|
|
|
|
|
|
|
|
/* get hostname */
|
|
|
|
|
|
|
|
gethostname( hostname, sizeof hostname );
|
|
|
|
|
|
|
|
#ifdef _ARCH_MACOS
|
|
|
|
|
|
|
|
/* check if hostname is in dotted decimal notation - this is a Mac-Hack */
|
|
|
|
if ( dtm_parse_ipaddr( hostname, &tmp ) != DTMERROR ) {
|
|
|
|
strcpy( ipaddrstr , hostname );
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* lookup IP address */
|
|
|
|
|
|
|
|
if( (hp = gethostbyname(hostname)) == NULL ) {
|
|
|
|
DTMerrno = DTMHOST;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* extract dotted decimal address */
|
|
|
|
|
|
|
|
{
|
|
|
|
struct in_addr inaddr ;
|
|
|
|
|
|
|
|
#ifdef _ARCH_MSDOS
|
|
|
|
inaddr = *((struct in_addr *)( hp -> h_addr)) ;
|
|
|
|
strcpy( ipaddrstr , inet_ntoa( inaddr.s_addr ));
|
|
|
|
#else
|
|
|
|
inaddr = *((struct in_addr *)( hp -> h_addr_list[ 0 ])) ;
|
|
|
|
strcpy( ipaddrstr , inet_ntoa( inaddr ));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
DBGINT( "dtm_get_ipaddr: dotted decimal address = '%s'\n", ipaddrstr );
|
2013-03-09 18:59:42 -06:00
|
|
|
return inet_addr( ipaddrstr ) ;
|
2010-03-08 04:55:21 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function to acquire and bind a UDP or TCP port.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_socket_init(S_ADDR *sockaddr,int porttype,int fLogicalName )
|
|
|
|
#else
|
|
|
|
int dtm_socket_init( sockaddr, porttype, fLogicalName )
|
|
|
|
S_ADDR *sockaddr;
|
|
|
|
int porttype;
|
|
|
|
int fLogicalName;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
int sockfd;
|
|
|
|
int type;
|
|
|
|
int protocol;
|
|
|
|
int opt = 1;
|
|
|
|
int sockaddrsize = sizeof (struct sockaddr_in);
|
|
|
|
char buf[128];
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGMSG1( "dtm_socket_init: sockaddr -> s_addr = %x\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohl( sockaddr -> sin_addr.s_addr) );
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGMSG1( "dtm_socket_init: sockaddr -> sin_port = %d\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohs( sockaddr -> sin_port) );
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
sockaddr -> sin_family = AF_INET ;
|
2010-03-08 04:55:21 -06:00
|
|
|
if ( fLogicalName ) {
|
2013-03-09 18:59:42 -06:00
|
|
|
/*
|
|
|
|
Logical name had been supplied for makeport.
|
2010-03-08 04:55:21 -06:00
|
|
|
Assign port from system ( sin_port = 0 ), and accept
|
2013-03-09 18:59:42 -06:00
|
|
|
from all network interfaces for multi-homed host
|
2010-03-08 04:55:21 -06:00
|
|
|
( INADDR_ANY ).
|
|
|
|
*/
|
|
|
|
sockaddr -> sin_addr.s_addr = htonl( INADDR_ANY );
|
|
|
|
sockaddr -> sin_port = htons( 0 ) ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Acquire appropriate socket ( UDP or TCP ) */
|
|
|
|
|
|
|
|
if( porttype == INPORTTYPE ) {
|
|
|
|
sockaddr -> sin_addr.s_addr = htonl( INADDR_ANY );
|
|
|
|
type = SOCK_STREAM ;
|
|
|
|
protocol = IPPROTO_TCP ;
|
|
|
|
} else {
|
|
|
|
type = SOCK_DGRAM ;
|
|
|
|
protocol = IPPROTO_UDP ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( (sockfd = socket( sockaddr -> sin_family, type, protocol )) < 0 ) {
|
2013-03-09 18:59:42 -06:00
|
|
|
DTMerrno = DTMSOCK ;
|
2010-03-08 04:55:21 -06:00
|
|
|
DBGINT( "dtm_socket_init: socket create error %d", errno );
|
|
|
|
return DTMERROR ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set socket options. */
|
|
|
|
|
|
|
|
setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof opt );
|
|
|
|
setsockopt( sockfd, SOL_SOCKET, SO_RCVBUF, (char *)&buf_size, sizeof(int) );
|
|
|
|
if( porttype == INPORTTYPE ) {
|
|
|
|
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof opt );
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Bind name to socket */
|
|
|
|
|
|
|
|
DBGFLOW( "dtm_socket_init: Before bind\n" );
|
|
|
|
DBGINT( "dtm_socket_init: sockfd = %d\n", sockfd );
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_socket_init: sockaddr -> family = %d\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
sockaddr -> sin_family );
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_socket_init: sockaddr -> s_addr = %x\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohl( sockaddr -> sin_addr.s_addr) );
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_socket_init: sockaddr -> sin_port = %d\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohs( sockaddr -> sin_port) );
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if( bind( sockfd, (struct sockaddr *)sockaddr,
|
2010-03-08 04:55:21 -06:00
|
|
|
sizeof( struct sockaddr_in ) ) < 0 ) {
|
|
|
|
DTMerrno = DTMSOCK ;
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGMSG1( "dtm_socket_init: could not bind to sockaddr, errno = %d\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
errno );
|
|
|
|
return DTMERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Listen at socket for TCP port, buffer for 5 pending connections */
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
if( porttype == INPORTTYPE )
|
2010-03-08 04:55:21 -06:00
|
|
|
listen( sockfd, 5 );
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/*
|
2010-03-08 04:55:21 -06:00
|
|
|
Get the actual assigned (port) address ( netid/hostid/portid )
|
|
|
|
- netid/hostid from dtm_get_ipaddr(),portid from getsockname().
|
|
|
|
|
|
|
|
Netid/hostid and portid is in network byte order.
|
|
|
|
Assumption - host is not multi-homed.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/* get the port number */
|
|
|
|
if(getsockname(sockfd,(struct sockaddr *)sockaddr,&sockaddrsize)<0) {
|
|
|
|
DBGINT( "dtm_socket_init: Unable to get sin_port, errno %d\n", errno );
|
|
|
|
DTMerrno = DTMSOCK ;
|
|
|
|
return DTMERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* get the IP address */
|
|
|
|
if( (sockaddr -> sin_addr.s_addr = dtm_get_ipaddr( buf )) == 0) {
|
|
|
|
DBGFLOW( "dtm_socket_init: Unable to get s_addr\n" );
|
|
|
|
DTMerrno = DTMSOCK ;
|
|
|
|
return DTMERROR ;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBGFLOW( "dtm_socket_init: Verify nethostid/portid\n" );
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_socket_init: Nethostid = %x\n",
|
|
|
|
ntohl( sockaddr -> sin_addr.s_addr ) );
|
|
|
|
DBGINT( "dtm_socket_init: Portid = %d \n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohs( sockaddr -> sin_port ) );
|
|
|
|
|
|
|
|
DBGINT( "dtm_socket_init: exit sockfd = %d\n", sockfd );
|
|
|
|
|
|
|
|
return sockfd ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Function to get sockaddr if portname is specified in
|
|
|
|
physical portname format ( e.g. "kankakee:9900" )
|
|
|
|
|
|
|
|
Return value : 0 on success,
|
|
|
|
DTMERROR on error
|
|
|
|
|
|
|
|
Notes : Algorithm -
|
|
|
|
|
|
|
|
1. Check portname format.
|
|
|
|
2. If logical format, sockaddr.sin_addr.s_addr = 0
|
|
|
|
3. If physical format, fill in sockaddr.sin_port and
|
|
|
|
sockaddr.sin_addr.s_addr.
|
|
|
|
|
|
|
|
It returns:
|
|
|
|
sockaddr in network byte order.
|
|
|
|
*pfLogicalName = TRUE if the port is logical.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef DTM_PROTOTYPES
|
|
|
|
int dtm_init_sockaddr(struct sockaddr_in *sockaddr,char *portname,
|
|
|
|
int *pfLogicalName )
|
|
|
|
#else
|
|
|
|
int dtm_init_sockaddr( sockaddr, portname, pfLogicalName )
|
|
|
|
struct sockaddr_in *sockaddr ;
|
|
|
|
char *portname ; /* read-only */
|
|
|
|
int *pfLogicalName;
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
char *host ;
|
|
|
|
char *port ;
|
|
|
|
char lportname[ PNAMELEN ] ;
|
|
|
|
char hostname[ MAXHOSTNAMELEN ] ;
|
|
|
|
u_long saddr_temp;
|
|
|
|
|
|
|
|
strncpy( lportname, portname, PNAMELEN - 1 );
|
|
|
|
lportname[ PNAMELEN - 1 ] = '\0' ;
|
|
|
|
|
|
|
|
DBGFLOW( "dtm_init_sockaddr called\n" );
|
|
|
|
|
|
|
|
if( lportname[0] == ':' ) {
|
2013-03-09 18:59:42 -06:00
|
|
|
host = NULL ;
|
2010-03-08 04:55:21 -06:00
|
|
|
port = lportname + 1;
|
|
|
|
} else {
|
|
|
|
if( (port = strchr( lportname, ':' )) == NULL ) {
|
|
|
|
/* Logical format */
|
|
|
|
DBGSTR( "dtm_init_sockaddr: logical portname %s\n", lportname );
|
|
|
|
sockaddr -> sin_port = htons( 0 );
|
|
|
|
sockaddr -> sin_addr.s_addr = htonl(0);
|
|
|
|
*pfLogicalName = TRUE;
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_init_sockaddr: sin_port = %d\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohs( sockaddr->sin_port ));
|
|
|
|
return DTM_OK;
|
|
|
|
}
|
|
|
|
*port++ = '\0';
|
|
|
|
host = lportname;
|
|
|
|
}
|
|
|
|
*pfLogicalName = FALSE;
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
/*
|
|
|
|
Physical format - hostname is either in dotted decimal
|
2010-03-08 04:55:21 -06:00
|
|
|
notation ( call ipaddr() ) or direct or missing.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if( host == NULL ) {
|
|
|
|
gethostname( hostname, sizeof hostname );
|
|
|
|
host = hostname ;
|
2013-03-09 18:59:42 -06:00
|
|
|
}
|
2010-03-08 04:55:21 -06:00
|
|
|
DBGINT( "dtm_init_sockaddr: host %s\n", host );
|
|
|
|
DBGINT( "dtm_init_sockaddr: port %s\n", port );
|
|
|
|
|
|
|
|
if( dtm_parse_ipaddr( host, &saddr_temp ) == DTMERROR) {
|
|
|
|
struct hostent *hp ;
|
|
|
|
if( (hp = gethostbyname( host )) == NULL ) {
|
|
|
|
DBGFLOW("dtm_init_sockaddr: gethostbyname returns error\n");
|
|
|
|
DTMerrno = DTMHOST ;
|
|
|
|
return DTMERROR ;
|
|
|
|
} else {
|
|
|
|
#ifdef _ARCH_MSDOS
|
|
|
|
saddr_temp = ((struct in_addr *)(hp->h_addr))->s_addr;
|
|
|
|
#else
|
|
|
|
saddr_temp = ((struct in_addr *)(hp->h_addr_list[0]))->s_addr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sockaddr->sin_addr.s_addr = saddr_temp;
|
|
|
|
|
|
|
|
/* Fill in port id */
|
|
|
|
sockaddr -> sin_port = htons((unsigned short)atol( port ));
|
|
|
|
|
2013-03-09 18:59:42 -06:00
|
|
|
DBGINT( "dtm_init_sockaddr: nethostid = %x\n",
|
2010-03-08 04:55:21 -06:00
|
|
|
ntohl( sockaddr -> sin_addr.s_addr ));
|
|
|
|
DBGINT( "dtm_init_sockaddr: portid = %d\n", ntohs( sockaddr -> sin_port) );
|
|
|
|
|
|
|
|
return DTM_OK ;
|
|
|
|
}
|