Blame snmplib/winpipe.c

Packit fcad23
/*
Packit fcad23
  Copyright (c) Fabasoft R&D Software GmbH & Co KG, 2003
Packit fcad23
  oss@fabasoft.com
Packit fcad23
  Author: Bernhard Penz <bernhard.penz@fabasoft.com>
Packit fcad23
Packit fcad23
  Redistribution and use in source and binary forms, with or without
Packit fcad23
  modification, are permitted provided that the following conditions are met:
Packit fcad23
Packit fcad23
  *  Redistributions of source code must retain the above copyright notice,
Packit fcad23
     this list of conditions and the following disclaimer.
Packit fcad23
Packit fcad23
  *  Redistributions in binary form must reproduce the above copyright
Packit fcad23
     notice, this list of conditions and the following disclaimer in the
Packit fcad23
     documentation and/or other materials provided with the distribution.
Packit fcad23
Packit fcad23
  *  The name of Fabasoft R&D Software GmbH & Co KG or any of its subsidiaries, 
Packit fcad23
     brand or product names may not be used to endorse or promote products 
Packit fcad23
     derived from this software without specific prior written permission.
Packit fcad23
Packit fcad23
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY
Packit fcad23
  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit fcad23
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
Packit fcad23
  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
Packit fcad23
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit fcad23
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit fcad23
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
Packit fcad23
  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Packit fcad23
  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
Packit fcad23
  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
Packit fcad23
  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit fcad23
*/
Packit fcad23
Packit fcad23
#ifdef WIN32
Packit fcad23
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/types.h>
Packit fcad23
#include <net-snmp/library/snmp_assert.h>
Packit fcad23
#include <net-snmp/library/winpipe.h>
Packit fcad23
#include <io.h>
Packit fcad23
Packit fcad23
static int InitUPDSocket(SOCKET *sock, struct sockaddr_in *socketaddress)
Packit fcad23
{
Packit fcad23
	*sock = 0;
Packit fcad23
	memset(socketaddress, 0, sizeof(struct sockaddr_in));
Packit fcad23
Packit fcad23
	if( (*sock = socket(AF_INET, SOCK_DGRAM, 0)) == SOCKET_ERROR)
Packit fcad23
	{
Packit fcad23
		netsnmp_assert(GetLastError() != WSANOTINITIALISED);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
	socketaddress->sin_family = AF_INET;
Packit fcad23
	socketaddress->sin_addr.S_un.S_addr = htonl(INADDR_LOOPBACK);
Packit fcad23
	socketaddress->sin_port = 0;
Packit fcad23
Packit fcad23
	if(bind(*sock, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR)
Packit fcad23
	{
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int ConnectUDPSocket(SOCKET *sock, struct sockaddr_in *socketaddress, SOCKET *remotesocket)
Packit fcad23
{
Packit fcad23
	int size = sizeof(struct sockaddr);
Packit fcad23
	if (getsockname(*sock, (struct sockaddr *) socketaddress, &size) == SOCKET_ERROR)
Packit fcad23
	{
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	if(size != sizeof(struct sockaddr))
Packit fcad23
	{
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	if (connect(*remotesocket, (struct sockaddr *) socketaddress, sizeof(struct sockaddr)) == SOCKET_ERROR)
Packit fcad23
	{
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int TestUDPSend(SOCKET *sock, struct sockaddr_in *socketaddress)
Packit fcad23
{
Packit fcad23
	unsigned short port = socketaddress->sin_port;
Packit fcad23
Packit fcad23
	int bytessent = sendto(*sock, (char *) &port, sizeof(port), 0, NULL, 0);
Packit fcad23
	if(bytessent != sizeof(port))
Packit fcad23
	{
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
static int TestUDPReceive(SOCKET *sock, SOCKET *remotesocket, struct sockaddr_in *remotesocketaddress)
Packit fcad23
{
Packit fcad23
	struct sockaddr_in recvfromaddress;
Packit fcad23
	unsigned short readbuffer[2];
Packit fcad23
	int size = sizeof(struct sockaddr);
Packit fcad23
Packit fcad23
	int bytesreceived = recvfrom(*sock,(char *) &readbuffer, sizeof(readbuffer), 0, (struct sockaddr *) &recvfromaddress, &size) ;
Packit fcad23
	if(bytesreceived != sizeof(unsigned short) || size != sizeof(struct sockaddr) || readbuffer[0] != (unsigned short) remotesocketaddress->sin_port || recvfromaddress.sin_family != remotesocketaddress->sin_family || recvfromaddress.sin_addr.S_un.S_addr != remotesocketaddress->sin_addr.S_un.S_addr || recvfromaddress.sin_port != remotesocketaddress->sin_port)
Packit fcad23
	{
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
static void CloseUDPSocketPair(SOCKET *socketpair)
Packit fcad23
{
Packit fcad23
	if(socketpair[0] != INVALID_SOCKET)
Packit fcad23
	{
Packit fcad23
		closesocket(socketpair[0]);
Packit fcad23
	}
Packit fcad23
	if(socketpair[1] != INVALID_SOCKET)
Packit fcad23
	{
Packit fcad23
		closesocket(socketpair[1]);
Packit fcad23
	}
Packit fcad23
}
Packit fcad23
Packit fcad23
/*
Packit fcad23
	Windows unnamed pipe emulation, used to enable select()
Packit fcad23
	on a Windows machine for the CALLBACK (pipe-based) transport domain.
Packit fcad23
*/
Packit fcad23
int create_winpipe_transport(int *pipefds)
Packit fcad23
{
Packit fcad23
	SOCKET socketpair[2];
Packit fcad23
	struct sockaddr_in socketaddress[2];
Packit fcad23
Packit fcad23
	struct timeval waittime = {0, 200000};
Packit fcad23
	fd_set readset;
Packit fcad23
Packit fcad23
	if (InitUPDSocket(&socketpair[0], &socketaddress[0]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
	if (InitUPDSocket(&socketpair[1], &socketaddress[1]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	/*
Packit fcad23
		I have two UDP sockets - now lets connect them to each other.
Packit fcad23
	*/
Packit fcad23
Packit fcad23
	if (ConnectUDPSocket(&socketpair[0], &socketaddress[0], &socketpair[1]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
	if(ConnectUDPSocket(&socketpair[1], &socketaddress[1], &socketpair[0]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	/*
Packit fcad23
		The two sockets are connected to each other, now lets test the connection
Packit fcad23
		by sending the own port number.
Packit fcad23
	*/
Packit fcad23
	if(TestUDPSend(&socketpair[0], &socketaddress[0]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
	if(TestUDPSend(&socketpair[1], &socketaddress[1]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	/*
Packit fcad23
		Port numbers sent, now lets select() on the socketpair and check that 
Packit fcad23
		both messages got through
Packit fcad23
	*/
Packit fcad23
	FD_ZERO(&readset);
Packit fcad23
	FD_SET(socketpair[0], &readset);
Packit fcad23
	FD_SET(socketpair[1], &readset);
Packit fcad23
Packit fcad23
	/*
Packit fcad23
		For some unknown reason the timeout setting in the select call does not have
Packit fcad23
		the desired effect, and for yet another unknown reason a Sleep(1) solves this
Packit fcad23
		problem.
Packit fcad23
	*/
Packit fcad23
	Sleep(1);
Packit fcad23
	if(select(0, &readset, NULL, NULL, &waittime) != 2 || !FD_ISSET(socketpair[0], &readset) || !FD_ISSET(socketpair[1], &readset))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	/*
Packit fcad23
		Check if the packets I receive were really sent by me, and nobody else
Packit fcad23
		tried to sneak.
Packit fcad23
	*/
Packit fcad23
    if(TestUDPReceive(&socketpair[0], &socketpair[1], &socketaddress[1]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
	if(TestUDPReceive(&socketpair[1], &socketpair[0], &socketaddress[0]))
Packit fcad23
	{
Packit fcad23
		CloseUDPSocketPair(socketpair);
Packit fcad23
		return -1;
Packit fcad23
	}
Packit fcad23
Packit fcad23
	/*
Packit fcad23
		All sanity checks passed, I can return a "UDP pipe"
Packit fcad23
	*/
Packit fcad23
	pipefds[0] = (int) socketpair[0];
Packit fcad23
	pipefds[1] = (int) socketpair[1];
Packit fcad23
Packit fcad23
	return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
#endif /* WIN32 */
Packit fcad23