📄 tcplink.c
字号:
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: TCP/IP transport link for trap files.
*
****************************************************************************/
#if defined( __NT__ )
#pragma library("wsock32.lib")
#elif defined( __WINDOWS__ )
#pragma library("winsock.lib")
#endif
#if defined(__OS2__) && !defined(__386__)
#define OS2
#define _TCP_ENTRY __cdecl __far
#define BSD_SELECT
#endif
#if defined ( __NETWARE__ )
#define __FUNCTION_DATA_ACCESS
#endif
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifndef __LINUX__
#define socklen_t int
#endif
#if defined(__NT__) || defined(__WINDOWS__)
#include <winsock.h>
#else
#if defined(__OS2__)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <unistd.h>
#if !defined ( __NETWARE__ )
#include <sys/socket.h>
#endif
#if !defined ( __LINUX__ ) && !defined ( __NETWARE__ )
#include <sys/select.h>
#endif
#if !defined ( __NETWARE__ )
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#endif
#if defined(__OS2__) && !defined(__386__)
#include <netlib.h>
#elif defined(__UNIX__) || defined(__DOS__) || defined(__OS2__)
#include <arpa/inet.h>
#endif
#endif
#include <watcom.h>
#if defined(__DOS__)
#include <machtype.h>
#include <tcp.h>
#endif
#if defined ( __NETWARE__ )
#include "novhax.h"
#endif
#if defined ( __NETWARE__ )
#include "debugme.h"
#else
#define _DBG_THREAD( x )
#define _DBG_DR( x )
#define _DBG_EVENT( x )
#define _DBG_IO( x )
#define _DBG_MISC( x )
#define _DBG_IPX( x )
#define _DBG_NET( x )
#define _DBG_REQ( x )
#define _DBG_ERROR( x )
#endif
#include "packet.h"
#include "trptypes.h"
#include "trperr.h"
#include "bool.h"
#include "ifi.h"
#define DEFAULT_PORT 0xDEB
#ifndef IPPROTO_TCP
#define IPPROTO_TCP 6
#endif
int data_socket;
struct sockaddr_in socket_address;
struct hostent *hp;
static bool die = FALSE;
#ifdef SERVER
int control_socket;
#endif
#if defined(SERVER)
extern void ServMessage( char * );
#endif
#if defined(__UNIX__)
#define soclose( s ) close( s )
#elif defined(__NT__) || defined(__WINDOWS__)
#define soclose( s ) closesocket( s )
#elif defined(__NETWARE__)
#define soclose( s) close( s )
#endif
bool Terminate( void )
{
struct linger linger;
die = TRUE;
linger.l_onoff = 1;
linger.l_linger = 0;
setsockopt( data_socket, (int)SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof( linger ) );
soclose( data_socket );
data_socket = -1;
return( TRUE );
}
static unsigned FullGet( void *get, unsigned len )
{
unsigned rec, got;
got = len;
for( ;; ) {
rec = recv( data_socket, get, len, 0 );
if( die || rec == (unsigned)-1 ) return( REQUEST_FAILED );
#if defined(__OS2__)
/* OS/2 TCP/IP docs say that return value of 0 indicates closed
* connection; this is unlike other TCP/IP implementations.
*/
if( rec == 0 ) return( REQUEST_FAILED );
#endif
len -= rec;
if( len == 0 ) break;
get = (unsigned_8 *)get + rec;
}
return( got );
}
unsigned RemoteGet( char *rec, unsigned len )
{
unsigned_16 rec_len;
_DBG_NET(("RemoteGet\r\n"));
len = len;
if( FullGet( &rec_len, sizeof( rec_len ) ) != sizeof( rec_len ) ) {
return( REQUEST_FAILED );
}
CONV_LE_16( rec_len );
if( rec_len != 0 ) {
if( FullGet( rec, rec_len ) != rec_len ) {
return( REQUEST_FAILED );
}
}
_DBG_NET(("Got a packet - size=%d\r\n", rec_len));
return( rec_len );
}
unsigned RemotePut( char *rec, unsigned len )
{
unsigned_16 send_len;
_DBG_NET(("RemotePut\r\n"));
send_len = len;
CONV_LE_16( send_len );
if( die || send( data_socket, (void *)&send_len, sizeof( send_len ), 0 ) == -1 ) {
return( REQUEST_FAILED );
}
if( len != 0 ) {
if( die || send( data_socket, rec, len, 0 ) == -1 ) {
return( REQUEST_FAILED );
}
}
_DBG_NET(("RemotePut...OK\r\n"));
return( len );
}
static void nodelay( void )
{
struct protoent *proto;
int delayoff;
int p;
delayoff = 1;
proto = getprotobyname( "tcp" );
p = proto ? proto->p_proto : IPPROTO_TCP;
setsockopt( data_socket, p, TCP_NODELAY, (void *)&delayoff, sizeof( delayoff ) );
}
char RemoteConnect( void )
{
#ifdef SERVER
struct timeval timeout;
fd_set ready;
struct sockaddr dummy;
socklen_t dummy_len = sizeof( dummy );
FD_ZERO( &ready );
FD_SET( control_socket, &ready );
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
if( select( control_socket+1, &ready, 0, 0, &timeout ) > 0 ) {
data_socket = accept( control_socket, &dummy, &dummy_len );
if( data_socket != -1 ) {
nodelay();
_DBG_NET(("Found a connection\r\n"));
return( 1 );
}
}
#else
data_socket = socket( AF_INET, SOCK_STREAM, 0 );
if( data_socket >= 0 ) {
if( connect( data_socket, (struct sockaddr *)&socket_address,
sizeof( socket_address ) ) >= 0 ) {
nodelay();
return( 1 );
}
}
#endif
return( 0 );
}
void RemoteDisco( void )
{
_DBG_NET(("RemoteDisco\r\n"));
if( data_socket != -1 ) soclose( data_socket );
}
char *RemoteLink( char *name, char server )
{
struct servent *sp;
unsigned port;
#ifdef SERVER
socklen_t length;
#if !defined(__LINUX__) /* FIXME */
struct ifi_info *ifi, *ifihead;
struct sockaddr *sa;
#endif
char buff2[128];
_DBG_NET(("SERVER: Calling into RemoteLink\r\n"));
#if defined(__NT__) || defined(__WINDOWS__)
{
WSADATA data;
if( WSAStartup( 0x101, &data ) != 0 ) {
return( TRP_ERR_unable_to_initialize_TCPIP );
}
}
#endif
control_socket = socket(AF_INET, SOCK_STREAM, 0);
if( control_socket < 0 ) {
return( TRP_ERR_unable_to_open_stream_socket );
}
port = 0;
if( name == NULL || name[0] == '\0' )
name = "tcplink";
sp = getservbyname( name, "tcp" );
if( sp != NULL ) {
port = sp->s_port;
} else {
while( isdigit( *name ) ) {
port = port * 10 + (*name - '0');
++name;
}
if( port == 0 ) port = DEFAULT_PORT;
port = htons( port );
}
/* Name socket using wildcards */
socket_address.sin_family = AF_INET;
socket_address.sin_addr.s_addr = INADDR_ANY;
socket_address.sin_port = port;
if( bind( control_socket, (struct sockaddr *)&socket_address,
sizeof( socket_address ) ) ) {
return( TRP_ERR_unable_to_bind_stream_socket );
}
/* Find out assigned port number and print it out */
length = sizeof( socket_address );
if( getsockname( control_socket, (struct sockaddr *)&socket_address,
&length ) ) {
return( TRP_ERR_unable_to_get_socket_name );
}
sprintf( buff2, "%s%d", TRP_TCP_socket_number, ntohs( socket_address.sin_port ) );
ServMessage( buff2 );
_DBG_NET(("TCP: "));
_DBG_NET((buff2));
_DBG_NET(("\r\n"));
#if !defined(__LINUX__) /* FIXME */
/* Find and print TCP/IP interface addresses, ignore aliases */
ifihead = get_ifi_info(AF_INET, FALSE);
for( ifi = ifihead; ifi != NULL; ifi = ifi->ifi_next ) {
/* Ignore loopback interfaces */
if( ifi->flags & IFI_LOOP )
continue;
if( (sa = ifi->ifi_addr) != NULL ) {
sprintf( buff2, "%s%s", TRP_TCP_ip_address,
inet_ntoa( ((struct sockaddr_in*)sa)->sin_addr ) );
ServMessage( buff2 );
}
}
free_ifi_info( ifihead );
#endif
_DBG_NET(("Start accepting connections\r\n"));
/* Start accepting connections */
listen( control_socket, 5 );
#else
char *sock;
#if defined(__NT__) || defined(__WINDOWS__)
{
WSADATA data;
if( WSAStartup( 0x101, &data ) != 0 ) {
return( TRP_ERR_unable_to_initialize_TCPIP );
}
}
#endif
/* get port number out of name */
sock = name;
while( *sock != '\0' ) {
if( *sock == ':' ) {
*sock = '\0';
++sock;
break;
}
++sock;
}
if( sock[0] == '\0' )
sp = getservbyname( "tcplink", "tcp" );
else
sp = getservbyname( sock, "tcp" );
if( sp != NULL ) {
port = sp->s_port;
} else {
port = 0;
while( isdigit( *sock ) ) {
port = port * 10 + (*sock - '0');
++sock;
}
if( *sock != '\0' ) {
return( TRP_ERR_unable_to_parse_port_number );
}
if( port == 0 ) port = DEFAULT_PORT;
port = htons( port );
}
/* Setup for socket connect using name specified by command line. */
socket_address.sin_family = AF_INET;
/* OS/2's TCP/IP gethostbyname doesn't handle numeric addresses */
socket_address.sin_addr.s_addr = inet_addr( name );
if( socket_address.sin_addr.s_addr == -1UL ) {
hp = gethostbyname( name );
if( hp != 0 ) {
memcpy( &socket_address.sin_addr, hp->h_addr, hp->h_length );
} else {
return( TRP_ERR_unknown_host );
}
}
socket_address.sin_port = port;
#endif
server = server;
return( NULL );
}
void RemoteUnLink( void )
{
#ifdef SERVER
soclose( control_socket );
#else
Terminate();
#endif
#if defined(__NT__) || defined(__WINDOWS__)
WSACleanup();
#endif
#if defined(__DOS__)
sock_exit();
#endif
}
#ifdef SERVER
/* Functions to manage IP interface information lists */
#ifdef __OS2__
/* Actual implementation - feel free to port to other OSes */
#include <sys/ioctl.h>
#include <net/if.h>
struct ifi_info * get_ifi_info(int family, int doaliases)
{
struct ifi_info *ifi, *ifihead, **ifipnext;
int sockfd, len, lastlen, flags, myflags;
char *ptr, *buf, lastname[IFNAMSIZ], *cptr;
struct ifconf ifc;
struct ifreq *ifr, ifrcopy;
struct sockaddr_in *sinptr;
sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
lastlen = 0;
len = 20 * sizeof( struct ifreq ); /* initial buffer size guess */
for( ; ; ) {
buf = malloc( len );
ifc.ifc_len = len;
ifc.ifc_buf = buf;
if( ioctl( sockfd, SIOCGIFCONF, &ifc ) >= 0 ) {
if( ifc.ifc_len == lastlen )
break; /* success, len has not changed */
lastlen = ifc.ifc_len;
}
len += 10 * sizeof( struct ifreq ); /* increment */
free( buf );
}
ifihead = NULL;
ifipnext = &ifihead;
lastname[0] = 0;
for( ptr = buf; ptr < buf + ifc.ifc_len; ) {
ifr = (struct ifreq *) ptr;
len = max( sizeof( struct sockaddr ), ifr->ifr_addr.sa_len );
ptr += sizeof( ifr->ifr_name ) + len; /* for next one in buffer */
if( ifr->ifr_addr.sa_family != family )
continue; /* ignore if not desired address family */
myflags = 0;
if(( cptr = strchr( ifr->ifr_name, ':' )) != NULL )
*cptr = 0; /* replace colon will null */
if( strncmp( lastname, ifr->ifr_name, IFNAMSIZ ) == 0 ) {
if ( doaliases == 0 )
continue; /* already processed this interface */
myflags = IFI_ALIAS;
}
memcpy( lastname, ifr->ifr_name, IFNAMSIZ );
ifrcopy = *ifr;
ioctl( sockfd, SIOCGIFFLAGS, &ifrcopy );
flags = ifrcopy.ifr_flags;
if( !( flags & IFF_UP ) )
continue; /* ignore if interface not up */
ifi = calloc( 1, sizeof( struct ifi_info ));
*ifipnext = ifi; /* prev points to this new one */
ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
if (flags & IFF_LOOPBACK )
myflags |= IFI_LOOP;
ifi->ifi_flags = flags; /* IFF_xxx values */
ifi->flags = myflags; /* IFI_xxx values */
memcpy( ifi->ifi_name, ifr->ifr_name, IFI_NAME );
ifi->ifi_name[IFI_NAME-1] = '\0';
switch (ifr->ifr_addr.sa_family) {
case AF_INET:
sinptr = (struct sockaddr_in *) &ifr->ifr_addr;
if( ifi->ifi_addr == NULL ) {
ifi->ifi_addr = calloc( 1, sizeof(struct sockaddr_in) );
memcpy( ifi->ifi_addr, sinptr, sizeof( struct sockaddr_in ) );
}
break;
default:
break;
}
}
free( buf );
return( ifihead ); /* pointer to first structure in linked list */
}
void free_ifi_info(struct ifi_info *ifihead)
{
struct ifi_info *ifi, *ifinext;
for( ifi = ifihead; ifi != NULL; ifi = ifinext ) {
if( ifi->ifi_addr != NULL )
free( ifi->ifi_addr );
ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */
free( ifi ); /* the ifi_info{} itself */
}
}
#else
/* Stubbed out */
struct ifi_info * get_ifi_info(int family, int doaliases)
{
return NULL;
}
void free_ifi_info(struct ifi_info *ifihead)
{
}
#endif
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -