Exemplo n.º 1
0
CIpSocket::t_string CIpSocket::RecvFrom( unsigned long x_uMax, unsigned long x_uFlags )
{
	// Do we have a size limit?
	if ( 0 < x_uMax )
	{
		// Allocate buffer
		t_string sBuf;
		try{ sBuf.resize( x_uMax ); }
		catch( ... ) { return sBuf; }
		if ( sBuf.length() >= x_uMax )
		{
			// Attempt to read data
			unsigned int uRead = RecvFrom( &sBuf[ 0 ], x_uMax, 0, x_uFlags );

			// Accept as the length
			sBuf.resize( uRead );

		} // end if

		return sBuf;

	} // end if

	// Allocate buffer
	t_string sBuf;
	unsigned int uRead = 0, uOffset = 0;

	// Allocate space
	const unsigned int uMin = 1024;
	try{ sBuf.resize( uMin ); }
	catch( ... ) { return sBuf; }
	if ( sBuf.length() < uMin )
		return sBuf;

	// Read all available data
	while ( 0 < ( uRead = RecvFrom( &sBuf[ uOffset ], uMin, 0, x_uFlags ) )
			&& uRead >= (unsigned int)uMin )
	{
		// Allocate more space
		uOffset += uRead;
		try{ sBuf.resize( uOffset + uMin ); }
		catch( ... ) { return sBuf; }
		if ( sBuf.length() < uOffset + uMin )
			return sBuf;

	} // end while

	// Set the length
	sBuf.resize( uOffset + uRead );

	return sBuf;
}
Exemplo n.º 2
0
bool MockUDPSocket::RecvFrom(
    uint8_t *buffer,
    ssize_t *data_read,
    ola::network::IPV4Address &source) const {  // NOLINT
    uint16_t port;
    return RecvFrom(buffer, data_read, source, port);
}
Exemplo n.º 3
0
int CTCPConnect::GetCustLevel(CString StrCardNum,CString strIP,CString strPort,UINT iOverTime)
{
    if (StartSocket(strPort,strIP))
    {
        char cCardNum[30];
        CCommonConvert::CStringToChar(StrCardNum,cCardNum);
        SocketPackage package = MakePackage(cCardNum);
        int size = sizeof(package);
        SendTo((char*)&package,sizeof(package));
        CString CardNum = _T("cardnum:")+StrCardNum;
        WriteLogWithTime(CardNum);
        char CardRecv[255];
        BOOL RecvTemp = FALSE;
        setsockopt(m_tSocket,SOL_SOCKET,SO_RCVTIMEO,(char *)&iOverTime,sizeof(UINT));
        if (!RecvFrom(CardRecv,255))
        {
            return -1;
        }
        int iLevel = GetLevel(CardRecv);

        //RecvFrom()
        CloseSocket();
        return iLevel;
    }
    else
    {
        CString strErr = _T("socket启动失败");
        return -1;
    }

}
Exemplo n.º 4
0
long SDMDeletesub::Recv(long port)
{
	int result;
	result = RecvFrom(port);
	if (result <= 0)
		return SDM_MESSAGE_RECV_ERROR;
	return result;
}
Exemplo n.º 5
0
int MySocket::RecvFrom(void *buf, int bytes, int flags)
// Receive a block of data from a remote datagram socket 
// and do not return until all the bytes have been read. 
// Returns the total number of bytes received or -1 if 
// an error occurs.
{
  return RecvFrom(Mysocket, &remote_sin, buf, bytes, flags);
}
Exemplo n.º 6
0
int MySocket::RecvFrom(void *buf, int bytes, int seconds, int useconds, 
		       int flags)
// Receive a block of data from a remote datagram socket 
// and do not return until all the bytes have been read 
// or the timeout value has been exceeded. Returns the total 
// number of bytes received or -1 if an error occurs.
{
  return RecvFrom(Mysocket, &remote_sin, buf, bytes, seconds, useconds, flags);
}
Exemplo n.º 7
0
int 
Socket::RecvFrom (uint8_t* buf, uint32_t size, uint32_t flags,
                  Address &fromAddress)
{
  NS_LOG_FUNCTION (this << &buf << size << flags << &fromAddress);
  Ptr<Packet> p = RecvFrom (size, flags, fromAddress); 
  if (p == 0)
    {
      return 0;
    }
  p->CopyData (buf, p->GetSize ());
  return p->GetSize ();
}
Exemplo n.º 8
0
bool MockUDPSocket::RecvFrom(
    uint8_t *buffer,
    ssize_t *data_read,
    ola::network::IPV4SocketAddress *source) {  // NOLINT
    IPV4Address source_ip;
    uint16_t port;

    bool ok = RecvFrom(buffer, data_read, source_ip, port);
    if (ok) {
        *source = IPV4SocketAddress(source_ip, port);
    }
    return ok;
}
Exemplo n.º 9
0
////////////////////////////////////////////////////////////////////////////////
//	函数名:BOOL RecvFrom(
//				OUT LPSTR pszFrom,
//				OUT INT& nFromPort,
//				OUT CHAR *pszBuffer,
//				IN INT nBufferSize,
//				IN DWORD dwTimeout /*= DEFAULT_RECV_TIMEOUT*/ )
//	用  途:接收数据报
//	对全局变量的影响:无
//	参  数:
//		pszFrom     : 源地址
//		nFromPort   : 源地址端口
//		pszBuffer   : 缓冲区
//		nBufferSize : 缓冲区大小
//		dwTimeout   : 超时
//	返回值:BOOL
////////////////////////////////////////////////////////////////////////////////
BOOL CBufSocket::RecvFrom(OUT LPSTR pszFrom,OUT INT& nFromPort,OUT CHAR *pszBuffer,IN INT nBufferSize,IN DWORD dwTimeout /*= DEFAULT_RECV_TIMEOUT*/)
{
    SOCKADDR_IN sockAddrFrom;
    ZeroMemory(&sockAddrFrom,sizeof(sockAddrFrom));

    // 假设缓冲区足够大,不考虑缓冲区不够的情形
    if( RecvFrom(m_hSocket, (SOCKADDR *)&sockAddrFrom, sizeof(sockAddrFrom),pszBuffer,nBufferSize,dwTimeout) <= 0 )
        return FALSE;

    // 保存源地址
    LPSTR pFrom = inet_ntoa(sockAddrFrom.sin_addr);
    memcpy( pszFrom,pFrom,strlen(pFrom) );
    nFromPort = ntohs( sockAddrFrom.sin_port);

    return TRUE;
}
Exemplo n.º 10
0
int DzRecvFrom(
    int                     fd,
    void*                   buf,
    size_t                  len,
    int                     flags,
    struct sockaddr*        from,
    socklen_t*              fromlen
    )
{
    DzHost* host = GetHost();
    assert( host );
    assert( fd >= 0 );
    assert( ( fd & HANDLE_HOST_ID_MASK ) == host->hostId );

    return RecvFrom( host, fd, buf, len, flags, from, fromlen );
}
Exemplo n.º 11
0
void UDPStream::FlushRecv()
{
	struct timeval time_val;
	time_val.tv_sec = 0;
	time_val.tv_usec = 0;

	fd_set rset;
	FD_ZERO(&rset);
	FD_SET(m_socket, &rset);

	if(select(static_cast<int>(m_socket + 1), &rset, NULL, NULL, &time_val) >= 0)
	{
		if(FD_ISSET(m_socket, &rset) > 0)
		{
			RecvFrom();
		}
	}	
}
Exemplo n.º 12
0
// Attempts Radius authentication (with specifying retry interval and multiple server)
bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT secret_size, wchar_t *username, char *password, UINT interval, UCHAR *mschap_v2_server_response_20)
{
	UCHAR random[MD5_SIZE];
	UCHAR id;
	BUF *encrypted_password = NULL;
	BUF *user_name = NULL;
	//IP ip;
	bool ret = false;
	TOKEN_LIST *token;
	UINT i;
	LIST *ip_list;
	IPC_MSCHAP_V2_AUTHINFO mschap;
	bool is_mschap;
	char client_ip_str[MAX_SIZE];
	static UINT packet_id = 0;
	// Validate arguments
	if (server == NULL || port == 0 || (secret_size != 0 && secret == NULL) || username == NULL || password == NULL)
	{
		return false;
	}

	Zero(client_ip_str, sizeof(client_ip_str));
	if (c != NULL && c->FirstSock != NULL)
	{
		IPToStr(client_ip_str, sizeof(client_ip_str), &c->FirstSock->RemoteIP);
	}

	// Parse the MS-CHAP v2 authentication data
	Zero(&mschap, sizeof(mschap));
	is_mschap = ParseAndExtractMsChapV2InfoFromPassword(&mschap, password);

	// Split the server into tokens
	token = ParseToken(server, " ,;\t");

	// Get the IP address of the server
	ip_list = NewListFast(NULL);
	for(i = 0; i < token->NumTokens; i++)
	{
		IP *tmp_ip = Malloc(sizeof(IP));
		if (GetIP(tmp_ip, token->Token[i]))
		{
			Add(ip_list, tmp_ip);
		}
		else if (GetIPEx(tmp_ip, token->Token[i], true))
		{
			Add(ip_list, tmp_ip);
		}
		else
		{
			Free(tmp_ip);
		}
	}

	FreeToken(token);

	if(LIST_NUM(ip_list) == 0)
	{
		ReleaseList(ip_list);
		return false;
	}

	// Random number generation
	Rand(random, sizeof(random));

	// ID generation
	id = (UCHAR)(packet_id % 254 + 1);
	packet_id++;

	if (is_mschap == false)
	{
		// Encrypt the password
		encrypted_password = RadiusEncryptPassword(password, random, secret, secret_size);
		if (encrypted_password == NULL)
		{
			// Encryption failure
			ReleaseList(ip_list);
			return false;
		}
	}

	// Generate the user name packet
	user_name = RadiusCreateUserName(username);

	if (user_name != NULL)
	{
		// Generate a password packet
		BUF *user_password = (is_mschap ? NULL : RadiusCreateUserPassword(encrypted_password->Buf, encrypted_password->Size));
		BUF *nas_id = RadiusCreateNasId(CEDAR_SERVER_STR);

		if (is_mschap || user_password != NULL)
		{
			UINT64 start;
			UINT64 next_send_time;
			UCHAR tmp[MAX_SIZE];
			UINT recv_buf_size = 32768;
			UCHAR *recv_buf = MallocEx(recv_buf_size, true);
			// Generate an UDP packet
			BUF *p = NewBuf();
			UCHAR type = 1;
			SOCK *sock;
			USHORT sz = 0;
			UINT pos = 0;
			BOOL *finish = ZeroMallocEx(sizeof(BOOL) * LIST_NUM(ip_list), true);

			Zero(tmp, sizeof(tmp));

			WriteBuf(p, &type, 1);
			WriteBuf(p, &id, 1);
			WriteBuf(p, &sz, 2);
			WriteBuf(p, random, 16);
			WriteBuf(p, user_name->Buf, user_name->Size);

			if (is_mschap == false)
			{
				UINT ui;
				// PAP
				WriteBuf(p, user_password->Buf, user_password->Size);
				WriteBuf(p, nas_id->Buf, nas_id->Size);

				// Service-Type
				ui = Endian32(2);
				RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui));

				// NAS-Port-Type
				ui = Endian32(5);
				RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui));

				// Tunnel-Type
				ui = Endian32(1);
				RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui));

				// Tunnel-Medium-Type
				ui = Endian32(1);
				RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui));

				// Calling-Station-Id
				RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str));

				// Tunnel-Client-Endpoint
				RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str));
			}
			else
			{
				// MS-CHAP v2
				static UINT session_id = 0;
				USHORT us;
				UINT ui;
				char *ms_ras_version = "MSRASV5.20";
				UCHAR ms_chapv2_response[50];

				// Acct-Session-Id
				us = Endian16(session_id % 254 + 1);
				session_id++;
				RadiusAddValue(p, 44, 0, 0, &us, sizeof(us));

				// NAS-IP-Address
				if (c != NULL && c->FirstSock != NULL && c->FirstSock->IPv6 == false)
				{
					ui = IPToUINT(&c->FirstSock->LocalIP);
					RadiusAddValue(p, 4, 0, 0, &ui, sizeof(ui));
				}

				// Service-Type
				ui = Endian32(2);
				RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui));

				// MS-RAS-Vendor
				ui = Endian32(311);
				RadiusAddValue(p, 26, 311, 9, &ui, sizeof(ui));

				// MS-RAS-Version
				RadiusAddValue(p, 26, 311, 18, ms_ras_version, StrLen(ms_ras_version));

				// NAS-Port-Type
				ui = Endian32(5);
				RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui));

				// Tunnel-Type
				ui = Endian32(1);
				RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui));

				// Tunnel-Medium-Type
				ui = Endian32(1);
				RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui));

				// Calling-Station-Id
				RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str));

				// Tunnel-Client-Endpoint
				RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str));

				// MS-RAS-Client-Version
				RadiusAddValue(p, 26, 311, 35, ms_ras_version, StrLen(ms_ras_version));

				// MS-RAS-Client-Name
				RadiusAddValue(p, 26, 311, 34, client_ip_str, StrLen(client_ip_str));

				// MS-CHAP-Challenge
				RadiusAddValue(p, 26, 311, 11, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge));

				// MS-CHAP2-Response
				Zero(ms_chapv2_response, sizeof(ms_chapv2_response));
				Copy(ms_chapv2_response + 2, mschap.MsChapV2_ClientChallenge, 16);
				Copy(ms_chapv2_response + 2 + 16 + 8, mschap.MsChapV2_ClientResponse, 24);
				RadiusAddValue(p, 26, 311, 25, ms_chapv2_response, sizeof(ms_chapv2_response));

				// NAS-ID
				WriteBuf(p, nas_id->Buf, nas_id->Size);
			}

			SeekBuf(p, 0, 0);

			WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size);

			// Create a socket
			sock = NewUDPEx(0, IsIP6(LIST_DATA(ip_list, pos)));

			// Transmission process start
			start = Tick64();
			if(interval < RADIUS_RETRY_INTERVAL)
			{
				interval = RADIUS_RETRY_INTERVAL;
			}
			else if(interval > RADIUS_RETRY_TIMEOUT)
			{
				interval = RADIUS_RETRY_TIMEOUT;
			}
			next_send_time = start + (UINT64)interval;

			while (true)
			{
				UINT server_port;
				UINT recv_size;
				//IP server_ip;
				SOCKSET set;
				UINT64 now;

SEND_RETRY:
				//SendTo(sock, &ip, port, p->Buf, p->Size);
				SendTo(sock, LIST_DATA(ip_list, pos), port, p->Buf, p->Size);

				Debug("send to host:%u\n", pos);

				next_send_time = Tick64() + (UINT64)interval;

RECV_RETRY:
				now = Tick64();
				if (next_send_time <= now)
				{
					// Switch the host to refer
					pos++;
					pos = pos % LIST_NUM(ip_list);

					goto SEND_RETRY;
				}

				if ((start + RADIUS_RETRY_TIMEOUT) < now)
				{
					// Time-out
					break;
				}

				InitSockSet(&set);
				AddSockSet(&set, sock);
				Select(&set, (UINT)(next_send_time - now), NULL, NULL);

				recv_size = RecvFrom(sock, LIST_DATA(ip_list, pos), &server_port, recv_buf, recv_buf_size);

				if (recv_size == 0)
				{
					Debug("Radius recv_size 0\n");
					finish[pos] = TRUE;
					for(i = 0; i < LIST_NUM(ip_list); i++)
					{
						if(finish[i] == FALSE)
						{
							// Switch the host to refer
							pos++;
							pos = pos % LIST_NUM(ip_list);
							goto SEND_RETRY;
						}
					}
					// Failure
					break;
				}
				else if (recv_size == SOCK_LATER)
				{
					// Waiting
					goto RECV_RETRY;
				}
				else
				{
					// Check such as the IP address
					if (/*Cmp(&server_ip, &ip, sizeof(IP)) != 0 || */server_port != port)
					{
						goto RECV_RETRY;
					}
					// Success
					if (recv_buf[0] == 2)
					{
						ret = true;

						if (is_mschap && mschap_v2_server_response_20 != NULL)
						{
							// Cutting corners Zurukko
							UCHAR signature[] = {0x1A, 0x33, 0x00, 0x00, 0x01, 0x37, 0x1A, 0x2D, 0x00, 0x53, 0x3D, };
							UINT i = SearchBin(recv_buf, 0, recv_buf_size, signature, sizeof(signature));

							if (i == INFINITE || ((i + sizeof(signature) + 40) > recv_buf_size))
							{
								ret = false;
							}
							else
							{
								char tmp[MAX_SIZE];
								BUF *b;

								Zero(tmp, sizeof(tmp));
								Copy(tmp, recv_buf + i + sizeof(signature), 40);

								b = StrToBin(tmp);

								if (b != NULL && b->Size == 20)
								{
									WHERE;
									Copy(mschap_v2_server_response_20, b->Buf, 20);
								}
								else
								{
									WHERE;
									ret = false;
								}

								FreeBuf(b);
							}
						}
					}
					break;
				}
			}

			Free(finish);

			// Release the socket
			ReleaseSock(sock);

			FreeBuf(p);
			FreeBuf(user_password);

			Free(recv_buf);
		}

		FreeBuf(nas_id);
		FreeBuf(user_name);
	}

	// Release the ip_list
	for(i = 0; i < LIST_NUM(ip_list); i++)
	{
		IP *tmp_ip = LIST_DATA(ip_list, i);
		Free(tmp_ip);
	}
	ReleaseList(ip_list);

	// Release the memory
	FreeBuf(encrypted_password);

	return ret;
}
Exemplo n.º 13
0
void udp_relayX(Connection *Conn,int csc,int csv[])
{	int svsock;
	int sockv[1024],readyv[1024],sx; /* must be lt/eq FD_SESIZE */
	int nsock; /* number of clients */
	CStr(buff,0x8000);
	int rcc,wcc;
	int nready;
	CStr(ihost,64);
	int iport;
	CStr(svhost,64);
	int svport;
	const char *clhost;
	int clport;
	UDP_Assoc *ua;
	UDP_Assoc *udpav[MAXASSOC*4]; /**/
	int udpxv[MAXASSOC*4];
	int lastrelay,idle;
	const char *aaddr;
	int svportmap;
	int portnumv[64];
	int csi;
	int istcp[MAXASSOC];
	int ccc = 0; /* tcp clients */
	int usocks = 0; /* UDP SOCKS */
	int update = 0;
	int ai;

	/* is this necessary or effective ? */
	socks_addservers();

	if( MAXASSOC < UDPRELAY_MAXASSOC ){
		UDPRELAY_MAXASSOC = MAXASSOC;
	}
	sv1log("MAXIMA=udprelay:%d (max. udp assoc.)\n",UDPRELAY_MAXASSOC);

	if( (aaddr = gethostaddr(DST_HOST)) == NULL ){
		sv1log("#### ERROR: bad destination host [%s]\n",DST_HOST);
		return;
	}
	strcpy(svhost,aaddr);
	svport = DST_PORT;
	svportmap = DFLT_PORTMAP;
	if( svportmap ){
		/* get port numbers of incoming ports ... */
		for( csi = 0; csi < csc; csi++ ){
			portnumv[csi] = sockPort(csv[csi]) + svportmap;
			portnumv[csi] &= ~0x40000000; /* clear IS_PORTMAP */
		}
	}

	expand_fdset(MAXASSOC);
	uassocv = (UDP_Assoc**)calloc(MAXASSOC+1,sizeof(UDP_Assoc*));
	for( csi = 0; csi < csc; csi++ )
		sockv[csi] = csv[csi];
	for( csi = 0; csi < csc; csi++ )
		istcp[csi] = !isUDPsock(sockv[csi]);
	nsock = 0;
	lastrelay = 0;

	for(;;){
UPDATE:
		if( update ){
			int ai;
			update = 0;
			ccc = 0;
			for( ai = 0; ua = uassocv[ai]; ai++ ){
				if( ua->ua_clpriv ){
				udpxv[csc + ccc] = ai;
				udpav[csc + ccc] = ua;
				sockv[csc + ccc++] = ua->ua_clsock;
				}
			}
			nsock = 0;
			for( ai = 0; ua = uassocv[ai]; ai++ ){
				udpxv[csc+ccc + nsock] = ai;
				udpav[csc+ccc + nsock] = ua;
				sockv[csc+ccc + nsock++] = ua->ua_svsock;
			}
			usocks = 0;
			for( ai = 0; ua = uassocv[ai]; ai++ ){
				int ns = csc+ccc+nsock;
				if( 0 <= ua->ua_svSOCKS ){
					udpxv[ns+usocks] = ai;
					udpav[ns+usocks] = ua;
					sockv[ns+usocks] = ua->ua_svSOCKS;
					usocks++;
				}
			}
		}
		/*
		nready = PollIns(10*1000,csc+nsock+ccc,sockv,readyv);
		*/
		nready = PollIns(10*1000,csc+ccc+nsock+usocks,sockv,readyv);
		if( nready < 0 ){
			/*
			sv1log("UDPRELAY: ABORT PollIns(%d) = %d\n",nready);
			*/
			sv1log("UDPRELAY: ABORT PollIns(%d+%d+%d+%d)=%d\n",
				csc,ccc,nsock,usocks,nready);
			for( ai = 0; ai < csc+ccc+nsock+usocks; ai++ ){
				sv1log("[%2d] %d\n",ai,sockv[ai]);
			}
			break;
		}
		if( nready == 0 ){
			idle = time(0) - lastrelay;
			if( SERVER_TIMEOUT && lastrelay )
			if( SERVER_TIMEOUT < idle){
				sv1log("UDPRELAY: SERVER TIMEOUT (idle %ds)\n",
					idle);
				break;
			}
			killTimeouts(uassocv);
			/*
			nsock = getsocks(uassocv,&sockv[csc]);
			*/
			update = 1;
			continue;
		}
		lastrelay = time(0);

		for( sx = 0; sx < csc; sx++ )
		if( 0 < readyv[sx] && istcp[sx] ){
			CStr(local,256);
			CStr(remote,256);
			int clsk;
			strcpy(remote,"*:*");
			strcpy(local,"*:*");
			clsk = VSocket(Conn,"ACPT/",sockv[sx],AVStr(local),AVStr(remote),"");
/*
			setNonblockingIO("UDPRELAY-CL",clsk,1);
*/
			SetNonblockingIO("UDPRELAY-CL",clsk,1);
			iport = getpeerAddr(clsk,AVStr(ihost));
			if( clsk <= 0 || iport <= 0 ){
				sv1log("UDPRELAY: accept() errno=%d\n",errno);
				continue;
			}
			if( svportmap ){
				svport = portnumv[sx];
			}
			ua = newUA(Conn,uassocv,ihost,iport,svhost,svport);
			ua->ua_clsock = clsk;
			ua->ua_clpriv = 1;
			update = 1;
		}else
		if( 0 < readyv[sx] ){
			rcc = recvFromA(sockv[sx],AVStr(buff),sizeof(buff),0,AVStr(ihost),&iport);
			if( rcc <= 0 ){
				sv1log("UDPRELAY: recv() == 0, errno=%d\n",errno);
				break;
			}
			if( svportmap ){
				svport = portnumv[sx];
			}
			ua = findUAbysrc(uassocv,ihost,iport,svhost,svport);
			if( ua == NULL ){
				ua = newUA(Conn,uassocv,ihost,iport,svhost,svport);
				if( ua == NULL ){
					continue;
				}
				ua->ua_clsock = sockv[sx];
				if( ua->ua_svsock < 0 )
					continue;
				/*
				nsock = getsocks(uassocv,&sockv[csc]);
				*/
				update = 1;
			}
			toServ(ua,buff,rcc,svhost,svport,ihost,iport);
			/*
			ua->ua_mtime = time(0);
			ua->ua_upcnt++;
			ua->ua_upbytes += rcc;
			if( UDPRELAY_RPORT_FIX )
				wcc = Send(ua->ua_svsock,buff,rcc);
			else	wcc = SendTo(ua->ua_svsock,buff,rcc,svhost,svport);
			Verbose("TO SERV#%d: %s:%d %3d> %s:%d\n",
				ua->ua_id,ihost,iport,rcc,svhost,svport);
			*/
			if( nready == 1 )
				continue;
		}

		for( sx = csc; sx < csc+ccc; sx++ )
		if( 0 < readyv[sx] ){
			rcc = recv(sockv[sx],buff,sizeof(buff),0);
			if( rcc <= 0 ){
				int ux = getUAx(uassocv,udpav[sx]);
				if( ux < 0 ){
					sv1log("## delUA-CL(%d)?\n",ux);
					continue;
				}
				delUA(uassocv,ux,"TCPreset-CL",1);
				/* here udpxv[] becomes inconsistent */
				update = 1;
			}else{
				ua = udpav[sx];
				toServ(ua,buff,rcc,svhost,svport,NULL,0);
			}
		}

		/*
		for( sx = csc; sx < csc+nsock; sx++ ){
		*/
		for( sx = csc+ccc; sx < csc+ccc+nsock; sx++ ){
			if( readyv[sx] <= 0 )
				continue;
			ua = udpav[sx];
			svsock = sockv[sx];

			if( 0 <= ua->ua_svSOCKS )
			rcc = RecvFrom(svsock,buff,sizeof(buff),AVStr(ihost),&iport);
			else
			rcc = recvFromA(svsock,AVStr(buff),sizeof(buff),0,AVStr(ihost),&iport);

			if( rcc <= 0 ){
				if( ua->ua_svtcp ){
					int ux = getUAx(uassocv,udpav[sx]);
					if( ux < 0 ){
						sv1log("## delUA-SV(%d)?\n",ux);
						continue;
					}
					delUA(uassocv,ux,"TCPreset-SV",1);
					update = 1;
				}
				readyv[sx] = -1;
				continue;
			}

			/*
			ua = findUAbysock(uassocv,svsock);
			*/
			ua->ua_mtime = time(0);
			ua->ua_downcnt++;
			ua->ua_downbytes += rcc;
			clhost = ua->ua_clhost;
			clport = ua->ua_clport;
			/*
			wcc = SendTo(ua->ua_clsock,buff,rcc,clhost,clport);
			*/
			wcc = sendToA(ua->ua_clsock,buff,rcc,0,clhost,clport);

			Verbose("TO CLNT#%d: %s:%d <%-3d %s:%d\n",
				ua->ua_id,clhost,clport,rcc,ihost,iport);
		}
		for( sx = csc+ccc+nsock; sx < csc+ccc+nsock+usocks; sx++ ){
			int ux;
			if( readyv[sx] <= 0 )
				continue;
			ua = udpav[sx];
			ux = getUAx(uassocv,udpav[sx]);
			if( ux < 0 ){
				sv1log("## delUA-CTL(%d)?\n",ux);
				continue;
			}
			sv1log("## detected disconn. by SOCKS CTL [%d]\n",ux);
			delUA(uassocv,ux,"SOCKSCTLreset-SV",1);
			update = 1;
		}
	}
}
Exemplo n.º 14
0
Ptr<Packet>
Socket::RecvFrom (Address &fromAddress)
{
  NS_LOG_FUNCTION (this << &fromAddress);
  return RecvFrom (std::numeric_limits<uint32_t>::max (), 0, fromAddress);
}
Exemplo n.º 15
0
bool NetBase::CheckIn()
{    
    // check for incoming packets
    SOCKADDR_IN addr;
    memset (&addr, 0, sizeof(SOCKADDR_IN));
    socklen_t len = sizeof(SOCKADDR_IN);

    if (!input_buffer)
    {
        input_buffer = (char*) cs_malloc(MAXPACKETSIZE);

        if (!input_buffer)
        {
            Error2("Failed to cs_malloc %d bytes for packet buffer!\n",MAXPACKETSIZE);
            return false;
        }
    }

    // Connection must be initialized!
    CS_ASSERT(ready);
    
    int packetlen = RecvFrom (&addr, &len, (void*) input_buffer, MAXPACKETSIZE);

    if (packetlen <= 0)
    {
        return false;
    }
    // Identify the connection
    Connection* connection = GetConnByIP(&addr);

    // Extract the netpacket from the buffer and prep for use locally.
    psNetPacket *bufpacket = psNetPacket::NetPacketFromBuffer(input_buffer,packetlen);
    if (bufpacket==NULL)
    {
        char addrText[INET_ADDRSTRLEN];

        //for win32 for now only inet_ntoa as inet_ntop wasn't supported till vista.
        //it has the same degree of compatibility of the previous code and it's supported till win2000
        #ifdef WIN32
        strncpy(addrText, inet_ntoa(addr.sin_addr), INET_ADDRSTRLEN);
        #else
        //there was a failure in conversion if null
        if(!inet_ntop(addr.sin_family,&addr.sin_addr, addrText, sizeof(addrText)))
        {
            strncpy(addrText, "UNKNOWN", INET_ADDRSTRLEN);
        }
        #endif

        // The data received was too small to make a full packet.
        if (connection)
        {
            Debug4(LOG_NET, connection->clientnum, "Too short packet received from client %d (IP: %s) (%d bytes)", connection->clientnum, addrText, packetlen);
        }
        else
        {
            Debug3(LOG_NET, 0, "Too short packet received from IP address %s. (%d bytes) No existing connection from this IP.",
                addrText, packetlen);
        }
        return true; // Continue processing more packets if available
    }
    input_buffer = NULL; //input_buffer now hold by the bufpacket pointer.

    // Endian correction
    bufpacket->UnmarshallEndian();

    // Check for too-big packets - no harm in processing them, but probably a bug somewhere
    if (bufpacket->GetPacketSize() < static_cast<unsigned int>(packetlen))
    {
        char addrText[INET_ADDRSTRLEN];

        //for win32 for now only inet_ntoa as inet_ntop wasn't supported till vista.
        //it has the same degree of compatibility of the previous code and it's supported till win2000
        #ifdef WIN32
        strncpy(addrText, inet_ntoa(addr.sin_addr), INET_ADDRSTRLEN);
        #else
        //there was a failure in conversion if null
        if(!inet_ntop(addr.sin_family,&addr.sin_addr, addrText, sizeof(addrText)))
        {
            strncpy(addrText, "UNKNOWN", INET_ADDRSTRLEN);
        }
        #endif
        
        if (connection)
        {
            Debug5(LOG_NET, connection->clientnum, "Too long packet received from client %d (IP: %s) (%d bytes received, header reports %zu bytes)",
                connection->clientnum, addrText, packetlen, bufpacket->GetPacketSize());
        }
        else
        {
            
            Debug4(LOG_NET, 0,"Too long packet received from IP address %s. (%d bytes received, header reports %zu bytes) No existing connection from this IP.",
                   addrText, packetlen, bufpacket->GetPacketSize());
        }
    }

    //Create new net packet entry and transfer ownership of bufpacket to pkt.
    csRef<psNetPacketEntry> pkt;
    pkt.AttachNew(new psNetPacketEntry( bufpacket, 
            connection ? connection->clientnum : 0, packetlen));
    
    if(TEST_PACKETLOSS > 0.0 && randomgen->Get() < TEST_PACKETLOSS)
    {
        psNetPacket* packet = pkt->packet;
        int type = 0;

        if (packet->offset == 0) 
        {
            psMessageBytes* msg = (psMessageBytes*) packet->data;
            type = msg->type;
        }

        Error3("Packet simulated lost. Type %s ID %d.\n", type == 0 ? "Fragment" : (const char *)  GetMsgTypeName(type), pkt->packet->pktid);
        return true;
    }

    // ACK packets can get eaten by HandleAck
    if (HandleAck(pkt, connection, &addr))
    {
        return true;
    }

    // printf("Got packet with sequence %d.\n", pkt->packet->GetSequence());
    //
    // Check for doubled packets and drop them
    if (pkt->packet->pktid != 0)
    {
        if (connection && CheckDoublePackets (connection, pkt))
        {
#ifdef PACKETDEBUG
            Debug2(LOG_NET,0,"Dropping doubled packet (ID %d)\n", pkt->packet->pktid);
#endif
            return true;
        }
    }
    
#ifdef PACKETDEBUG
    Debug7(LOG_NET,0,"Received Pkt, ID: %d, offset %d, from %d size %d (actual %d) flags %d\n", 
        pkt->packet->pktid, pkt->packet->offset, pkt->clientnum, pkt->packet->pktsize,packetlen, pkt->packet->flags);
#endif

    /**
    * Now either send this packet to BuildMessage, or loop through
    * subpackets if they are merged.
    */
    csRef<psNetPacketEntry> splitpacket = pkt;
    psNetPacket      *packetdata = NULL;

    do
    {
        splitpacket = pkt->GetNextPacket(packetdata);
        if (splitpacket)
            BuildMessage(splitpacket, connection, &addr);
    } while (packetdata);
    return true;
}
Exemplo n.º 16
0
bool MockUDPSocket::RecvFrom(uint8_t *buffer, ssize_t *data_read) const {
    IPV4Address address;
    uint16_t port;
    return RecvFrom(buffer, data_read, address, port);
}
Exemplo n.º 17
0
// Polling process
void UdpAccelPoll(UDP_ACCEL *a)
{
	UCHAR *tmp = a->TmpBuf;
	IP nat_t_ip;
	UINT num_ignore_errors = 0;
	// Validate arguments
	if (a == NULL)
	{
		return;
	}

	Lock(a->NatT_Lock);
	{
		Copy(&nat_t_ip, &a->NatT_IP, sizeof(IP));
	}
	Unlock(a->NatT_Lock);

	if (IsZeroIp(&nat_t_ip) == false)
	{
		// Release the thread which gets the IP address of the NAT-T server because it is no longer needed
		if (a->NatT_GetIpThread != NULL)
		{
			WaitThread(a->NatT_GetIpThread, INFINITE);
			ReleaseThread(a->NatT_GetIpThread);
			a->NatT_GetIpThread = NULL;
		}
	}

	// Receive a new UDP packet
	while (true)
	{
		IP src_ip;
		UINT src_port;
		UINT ret;

		ret = RecvFrom(a->UdpSock, &src_ip, &src_port, tmp, UDP_ACCELERATION_TMP_BUF_SIZE);

		if (ret != 0 && ret != SOCK_LATER)
		{
			if (a->UseUdpIpQuery && a->UdpIpQueryPacketSize >= 8 && CmpIpAddr(&a->UdpIpQueryHost, &src_ip) == 0 &&
				src_port == a->UdpIpQueryPort)
			{
				// Receive a response of the query for IP and port number
				IP my_ip = {0};
				UINT myport = 0;
				BUF *b = MemToBuf(a->UdpIpQueryPacketData, a->UdpIpQueryPacketSize);


				FreeBuf(b);
			}
			else if (IsZeroIp(&nat_t_ip) == false && CmpIpAddr(&nat_t_ip, &src_ip) == 0 &&
				src_port == UDP_NAT_T_PORT)
			{
				// Receive a response from the NAT-T server
				IP my_ip;
				UINT myport;

				if (RUDPParseIPAndPortStr(tmp, ret, &my_ip, &myport))
				{
					if (myport >= 1 && myport <= 65535)
					{
						if (a->MyPortByNatTServer != myport)
						{
							a->MyPortByNatTServer = myport;
							a->MyPortByNatTServerChanged = true;
							a->CommToNatT_NumFail = 0;

							Debug("NAT-T: MyPort = %u\n", myport);
						}
					}
				}
/*
				BUF *b = NewBuf();
				PACK *p;

				WriteBuf(b, tmp, ret);
				SeekBufToBegin(b);

				p = BufToPack(b);
				if (p != NULL)
				{
					if (PackCmpStr(p, "opcode", "query_for_nat_traversal"))
					{
						if (PackGetBool(p, "ok"))
						{
							if (PackGetInt64(p, "tran_id") == a->NatT_TranId)
							{
								UINT myport = PackGetInt(p, "your_port");

								if (myport >= 1 && myport <= 65535)
								{
									if (a->MyPortByNatTServer != myport)
									{
										a->MyPortByNatTServer = myport;
										a->MyPortByNatTServerChanged = true;

										Debug("NAT-T: MyPort = %u\n", myport);
									}
								}
							}
						}
					}

					FreePack(p);
				}

				FreeBuf(b);*/
			}
			else
			{
				BLOCK *b = UdpAccelProcessRecvPacket(a, tmp, ret, &src_ip, src_port);

				//Debug("UDP Recv: %u %u %u\n", ret, (b == NULL ? 0 : b->Size), (b == NULL ? 0 : b->Compressed));

				/*if (b != NULL)
				{
					char tmp[MAX_SIZE * 10];
					BinToStr(tmp, sizeof(tmp), b->Buf, b->Size);
					Debug("Recv Pkt: %s\n", tmp);
				}*/

				if (b != NULL)
				{
					// Receive a packet
					InsertQueue(a->RecvBlockQueue, b);
				}
			}
		}
		else
		{
			if (ret == 0)
			{
				if (a->UdpSock->IgnoreRecvErr == false)
				{
					// Serious UDP reception error occurs
					a->FatalError = true;
					break;
				}

				if ((num_ignore_errors++) >= MAX_NUM_IGNORE_ERRORS)
				{
					a->FatalError = true;
					break;
				}
			}
			else
			{
				// SOCK_LATER
				break;
			}
		}
	}

	// Send a Keep-Alive packet
	if (a->NextSendKeepAlive == 0 || (a->NextSendKeepAlive <= a->Now) || a->YourPortByNatTServerChanged)
	{
		a->YourPortByNatTServerChanged = false;

		if (UdpAccelIsSendReady(a, false))
		{
			UINT rand_interval;

			if (a->FastDetect == false)
			{
				rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN;
			}
			else
			{
				rand_interval = rand() % (UDP_ACCELERATION_KEEPALIVE_INTERVAL_MAX_FAST - UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST) + UDP_ACCELERATION_KEEPALIVE_INTERVAL_MIN_FAST;
			}

			a->NextSendKeepAlive = a->Now + (UINT64)rand_interval;

			//Debug("UDP KeepAlive\n");

			UdpAccelSend(a, NULL, 0, false, 1000, false);
		}
	}

	// Send a NAT-T request packet (Only if the connection by UDP has not be established yet)
	if (a->NoNatT == false)
	{
		// In the usual case
		if (IsZeroIp(&nat_t_ip) == false)
		{
			if (UdpAccelIsSendReady(a, true) == false)
			{
				if (a->NextPerformNatTTick == 0 || (a->NextPerformNatTTick <= a->Now))
				{
					UINT rand_interval;
					UCHAR c = 'B';

					a->CommToNatT_NumFail++;
					
					rand_interval = UDP_NAT_T_INTERVAL_INITIAL * MIN(a->CommToNatT_NumFail, UDP_NAT_T_INTERVAL_FAIL_MAX);
					//PACK *p = NewPack();
					//BUF *b;

					if (a->MyPortByNatTServer != 0)
					{
						rand_interval = GenRandInterval(UDP_NAT_T_INTERVAL_MIN, UDP_NAT_T_INTERVAL_MAX);
					}

					a->NextPerformNatTTick = a->Now + (UINT64)rand_interval;

					// Generate the request packet
					/*PackAddStr(p, "description", UDP_NAT_T_SIGNATURE);
					PackAddStr(p, "opcode", "query_for_nat_traversal");
					PackAddInt64(p, "tran_id", a->NatT_TranId);
					b = PackToBuf(p);
					FreePack(p);*/

					// Send the request packet
					SendTo(a->UdpSock, &nat_t_ip, UDP_NAT_T_PORT, &c, 1);

					//FreeBuf(b);
				}
			}
			else
			{
				a->NextPerformNatTTick = 0;
				a->CommToNatT_NumFail = 0;
			}
		}
	}
	else
	{
		// NAT_T is disabled, but there is a reference host (such as VGC)
		if (a->UseUdpIpQuery || a->UseSuperRelayQuery)
		{
		}
	}
}
Exemplo n.º 18
0
/*!\brief Lese-Timeout festlegen
 *
 * Mit dieser Funktion kann ein Timeout für Lesezugriffe gesetzt werden. Normalerweise
 * blockiert eine Leseoperation mit "Read" solange, bis die angeforderten Daten
 * eingegangen sind (ausser der Socket wurde mit TCPSocket::setBlocking auf "Non-Blocking"
 * gesetzt). Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer
 * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus
 * \p seconds + \p useconds.
 * \par
 * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als
 * Wert für \p seconds und \p useconds aufgerufen werden.
 *
 * @param[in] seconds Anzahl Sekunden
 * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde)
 * @exception NotConnectedException
 * @exception InvalidSocketException
 * @exception BadFiledescriptorException
 * @exception UnknownOptionException
 * @exception BadAddressException
 * @exception InvalidArgumentsException
 */
void UDPSocket::setTimeoutRead(int seconds, int useconds)
{
	if (!connected)
		throw NotConnectedException();
	struct timeval tv;
	tv.tv_sec = seconds;
	tv.tv_usec = useconds;
	PPLSOCKET *s = (PPLSOCKET*) socket;
#ifdef WIN32
	if (setsockopt(s->sd,SOL_SOCKET,SO_RCVTIMEO,(const char*)&tv,sizeof(tv))!=0) {
#else
	if (setsockopt(s->sd, SOL_SOCKET, SO_RCVTIMEO, (void*) &tv, sizeof(tv)) != 0) {
#endif
		throwExceptionFromErrno(errno, "setTimeoutRead");
	}
}

/*!\brief Schreib-Timeout festlegen
 *
 * Mit dieser Funktion kann ein Timeout für Schreibzugriffe gesetzt werden. Normalerweise
 * blockiert eine Schreiboperation mit "Write" solange, bis alle Daten gesendet wurden.
 * Mit dieser Funktion kann jedoch ein beliebiger mikrosekunden genauer
 * Timeout festgelegt werden. Der Timeout errechnet sich dabei aus
 * \p seconds + \p useconds.
 * \par
 * Um den Timeout wieder abzustellen, kann die Funktion mit 0 als
 * Wert für \p seconds und \p useconds aufgerufen werden.
 *
 * @param[in] seconds Anzahl Sekunden
 * @param[in] useconds Anzahl Mikrosekunden (1000000 Mikrosekunden = 1 Sekunde)
 * @exception NotConnectedException
 * @exception InvalidSocketException
 * @exception BadFiledescriptorException
 * @exception UnknownOptionException
 * @exception BadAddressException
 * @exception InvalidArgumentsException
 */
void UDPSocket::setTimeoutWrite(int seconds, int useconds)
{
	if (!connected)
		throw NotConnectedException();
	struct timeval tv;
	tv.tv_sec = seconds;
	tv.tv_usec = useconds;
	PPLSOCKET *s = (PPLSOCKET*) socket;
#ifdef WIN32
	if (setsockopt(s->sd,SOL_SOCKET,SO_SNDTIMEO,(const char*)&tv,sizeof(tv))!=0) {
#else
	if (setsockopt(s->sd, SOL_SOCKET, SO_SNDTIMEO, (void*) &tv, sizeof(tv)) != 0) {
#endif
		throwExceptionFromErrno(errno, "setTimeoutRead");
	}
}

/*!\brief Auf eingehende Daten warten
 *
 * \desc
 * Diese Funktion prüft, ob Daten eingegangen sind. Ist dies der Fall,
 * kehrt sie sofort wieder zurück. Andernfalls wartet sie solange, bis
 * Daten eingehen, maximal aber die mit \p seconds und \p useconds
 * angegebene Zeitspanne. Falls \p seconds und \p useconds Null sind, und
 * keine Daten bereitstehen, kehrt die Funktion sofort zurück.
 *
 * @param[in] seconds Anzahl Sekunden, die gewartet werden soll
 * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll
 * @return Die Funktion gibt \b true zurück, wenn Daten zum Lesen bereitstehen,
 * sonst \b false. Im Fehlerfall wird eine Exception geworfen.
 * @exception Diverse
 */
bool UDPSocket::waitForIncomingData(int seconds, int useconds)
{
	if (!connected) throw NotConnectedException();
	PPLSOCKET *s=(PPLSOCKET*)socket;
	fd_set rset, wset, eset;
	struct timeval timeout;

	timeout.tv_sec=seconds;
	timeout.tv_usec=useconds;

	FD_ZERO(&rset);
	FD_ZERO(&wset);
	FD_ZERO(&eset);
	FD_SET(s->sd,&rset); // Wir wollen nur prüfen, ob was zu lesen da ist
	int ret=select(s->sd+1,&rset,&wset,&eset,&timeout);
	if (ret<0) {
		throwExceptionFromErrno(errno, "UDPSocket::waitForIncomingData");
	}
	if (FD_ISSET(s->sd,&eset)) {
		throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData");
	}
	// Falls Daten zum Lesen bereitstehen, könnte dies auch eine Verbindungstrennung anzeigen
	if (FD_ISSET(s->sd,&rset)) {
		char buf[2];
		ret=recv(s->sd, buf,1, MSG_PEEK|MSG_DONTWAIT);
		// Kommt hier ein Fehler zurück?
		if (ret<0) {
			throwExceptionFromErrno(errno, "UDPSocket::isReadable");
		}
		// Ein Wert von 0 zeigt an, dass die Verbindung getrennt wurde
		if (ret==0) {
			throw BrokenPipeException();
		}
		return true;
	}
	return false;
}

/*!\brief Warten, bis der Socket beschreibbar ist
 *
 * \desc
 * Diese Funktion prüft, ob Daten auf den Socket geschrieben werden können.
 * Ist dies der Fall, kehrt sie sofort wieder zurück. Andernfalls wartet
 * sie solange, bis der Socket beschrieben werden kann, maximal aber die
 * mit \p seconds und \p useconds angegebene Zeitspanne.
 * Falls \p seconds und \p useconds Null sind, und
 * keine Daten gesendet werden können, kehrt die Funktion sofort zurück.
 *
 * @param[in] seconds Anzahl Sekunden, die gewartet werden soll
 * @param[in] useconds Anzahl Mikrosekunden, die gewartet werden soll
 * @return Die Funktion gibt \b true zurück, wenn Daten geschrieben werden können,
 * sonst \b false. Im Fehlerfall wird eine Exception geworfen.
 * @exception Diverse
 *
 */
bool UDPSocket::waitForOutgoingData(int seconds, int useconds)
{
	if (!connected) throw NotConnectedException();
	PPLSOCKET *s=(PPLSOCKET*)socket;
	fd_set rset, wset, eset;
	struct timeval timeout;
	timeout.tv_sec=seconds;
	timeout.tv_usec=useconds;

	FD_ZERO(&rset);
	FD_ZERO(&wset);
	FD_ZERO(&eset);
	FD_SET(s->sd,&wset); // Wir wollen nur prüfen, ob wir schreiben können
	int ret=select(s->sd+1,&rset,&wset,&eset,&timeout);
	if (ret<0) {
		throwExceptionFromErrno(errno, "UDPSocket::waitForOutgoingData");
	}
	if (FD_ISSET(s->sd,&eset)) {
		throw OutOfBandDataReceivedException("UDPSocket::waitForIncomingData");
	}
	if (FD_ISSET(s->sd,&wset)) {
		return true;
	}
	return false;
}

/*!\brief Bei Lesezugriffen blockieren
 *
 * \desc
 * Durch Aufruf dieser Funktion kann festgelegt werden, ob der Socket bei Lesezugriffen
 * blockieren soll. Nach dem Öffnen des Sockets ist dieser defaultmäßig so
 * eingestellt, dass er bei Lesezugriffen solange blockiert (wartet), bis Daten zur
 * Verfügung stehen. Wird er auf "Non-Blocking" gestellt, kehren die Lese-Funktionen
 * sofort mit einer Fehlermeldung zurück, wenn noch keine Daten bereitstehen.
 *
 * @param[in] value Der Wert "true" setzt den Socket in den Blocking-Modus, was auch der
 * Default ist. Durch den Wert "false" wird er in den Non-Blocking-Modus gesetzt.
 * @exception Diverse
 */
void UDPSocket::setBlocking(bool value)
{
	PPLSOCKET *s=(PPLSOCKET*)socket;
	if((!s) || (!s->sd)) throw NotConnectedException();
	int ret=0;
#ifdef _WIN32
	u_long v;
	if (value) {
		v=0;
		ret=ioctlsocket(s->sd,FIONBIO,NULL);
	} else {
		v=1;
		ret=ioctlsocket(s->sd,FIONBIO,&v);
	}
	if (ret==0) return;
	throwExceptionFromErrno(errno, "UDPSocket::setBlocking");
#else
	if (value)
	    ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)&(~O_NONBLOCK)); // Blocking
	else
		ret=fcntl(s->sd,F_SETFL,fcntl(s->sd,F_GETFL,0)|O_NONBLOCK);// NON-Blocking
	if (ret<0) throwExceptionFromErrno(errno, "UDPSocket::setBlocking");
#endif
}



/*!\brief Socket auf eine IP-Adresse und Port binden
 *
 * \desc
 * Diese Funktion muss aufgerufen werden, bevor man mit CTCPSocket::Listen einen TCP-Server starten kann. Dabei wird mit \p host
 * die IP-Adresse festgelegt, auf die sich der Server binden soll und mit \p port der TCP-Port.
 * Es ist nicht möglich einen Socket auf mehrere Adressen zu binden.
 *
 * @param[in] host IP-Adresse, Hostname oder "*". Bei Angabe von "*" bindet sich der Socket auf alle
 * Interfaces des Servers.
 * @param[in] port Der gewünschte TCP-Port
 * @exception OutOfMemoryException
 * @exception ResolverException
 * @exception SettingSocketOptionException
 * @exception CouldNotBindToInterfaceException
 * @exception CouldNotOpenSocketException
 */
void UDPSocket::bind(const String &host, int port)
{
	//int addrlen=0;
	if (!socket) {
		socket=malloc(sizeof(PPLSOCKET));
		if (!socket) throw OutOfMemoryException();
		PPLSOCKET *s=(PPLSOCKET*)socket;
		s->sd=0;
		s->proto=6;
		s->ipname=NULL;
		s->port=port;
		//s->addrlen=0;
	}
#ifdef _WIN32
	SOCKET listenfd=0;
#else
	int listenfd=0;
#endif

	PPLSOCKET *s=(PPLSOCKET*)socket;
	if (s->sd) disconnect();
	if (s->ipname) free(s->ipname);
	s->ipname=NULL;

	struct addrinfo hints;
	memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_flags=AI_PASSIVE;
	hints.ai_family=AF_UNSPEC;
	hints.ai_socktype=SOCK_DGRAM;
	int on=1;
	// Prüfen, ob host ein Wildcard ist
	struct addrinfo *res;
	if (host.notEmpty()==true && host!="*") {
		char portstr[10];
		sprintf(portstr,"%i",port);
		int n;
		if ((n=getaddrinfo(host,portstr,&hints,&res))!=0) {
			throw ResolverException("%s, %s",(const char*)host,gai_strerror(n));
		}
		struct addrinfo *ressave=res;
		do {
			listenfd=::socket(res->ai_family,res->ai_socktype,res->ai_protocol);
			if (listenfd<0) continue; // Error, try next one
#ifdef _WIN32
			if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,(const char*)&on,sizeof(on))!=0) {
#else
			if (setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))!=0) {
#endif
				freeaddrinfo(ressave);
				throw SettingSocketOptionException();
			}
			if (::bind(listenfd,res->ai_addr,res->ai_addrlen)==0) {
				//addrlen=res->ai_addrlen;
				break;
			}
			::shutdown(listenfd,2);
#ifdef _WIN32
			closesocket(listenfd);
#else
			close(listenfd);
#endif
			listenfd=0;

		} while ((res=res->ai_next)!=NULL);
		freeaddrinfo(ressave);
	} else {
		// Auf alle Interfaces binden
		listenfd=::socket(AF_INET, SOCK_STREAM, 0);
		if (listenfd>=0) {
			struct sockaddr_in addr;
			memset(&addr,0,sizeof(addr));
			addr.sin_addr.s_addr = htonl(INADDR_ANY);
			addr.sin_port = htons(port);
			addr.sin_family = AF_INET;
			/* bind server port */
			if(::bind(listenfd, (struct sockaddr *) &addr, sizeof(addr))!=0) {
				::shutdown(listenfd,2);
#ifdef _WIN32
				closesocket(listenfd);
#else
				close(listenfd);
#endif
				throw CouldNotBindToInterfaceException("Host: *, Port: %d",port);
			}
			s->sd=listenfd;
			connected=1;
			return;
		}
	}
	if (listenfd<0) {
		throw CouldNotOpenSocketException("Host: %s, Port: %d",(const char*)host,port);
	}
	if (res==NULL) {
		throw CouldNotBindToInterfaceException("Host: %s, Port: %d",(const char*)host,port);
	}
	s->sd=listenfd;
	connected=1;
}



/*!\brief Daten schreiben
 *
 * \desc
 * Mit dieser Funktionen werden \p bytes Bytes aus dem Speicherbereich \p buffer an die Gegenstelle
 * gesendet.
 *
 * @param[in] buffer Pointer auf die zu sendenden Daten
 * @param[in] bytes Anzahl zu sendender Bytes
 * @return Wenn die Daten erfolgreich geschrieben wurden, gibt die Funktion die Anzahl geschriebener
 * Bytes zurück. Im Fehlerfall wird eine Exception geworfen.
 */
size_t UDPSocket::write(const void *buffer, size_t bytes)
{
	if (!connected)
		throw NotConnectedException();
	PPLSOCKET *s = (PPLSOCKET*) socket;
	if (!buffer)
		throw InvalidArgumentsException();
	size_t BytesWritten = 0;
	if (bytes) {
		size_t rest = bytes;
		ssize_t b = 0;
		while (rest) {
			b = ::send(s->sd, (char *) buffer, rest, 0);
			if (b > 0) {
				BytesWritten += b;
				rest -= b;
				buffer = ((const char*) buffer) + b;
			}
#ifdef WIN32
			if (b==SOCKET_ERROR) {
#else
			if (b < 0) {
#endif
				if (errno == EAGAIN) {
					waitForOutgoingData(0, 100000);
				} else {
					throwExceptionFromErrno(errno, "UDPSocket::write");
				}
			}
		}
	}
	return BytesWritten;
}

size_t UDPSocket::write(const String &str, size_t bytes)
{
	if (bytes>0 && bytes<=str.size()) {
		return write(str.getPtr(),bytes);
	}
	return write(str.getPtr(),str.size());
}

size_t UDPSocket::write(const WideString &str, size_t bytes)
{
	if (bytes>0 && bytes<=str.byteLength()) {
		return write(str.getPtr(),bytes);
	}
	return write(str.getPtr(),str.byteLength());
}

size_t UDPSocket::write(const ByteArrayPtr &bin, size_t bytes)
{
	if (bytes>0 && bytes<=bin.size()) {
		return write(bin.ptr(),bytes);
	}
	return write(bin.ptr(),bin.size());
}

size_t UDPSocket::writef(const char *fmt, ...)
{
	if (!fmt) throw IllegalArgumentException();
	String str;
	va_list args;
	va_start(args, fmt);
	str.vasprintf(fmt,args);
	va_end(args);
	return write(str);
}

#ifdef TODO

	void UDPSocket::setTimeoutRead(int seconds, int useconds)
	/*! \brief Timeout setzen
	 *
	 * \header \#include <ppl6.h>
	 * \desc
	 * Mit dieser Funktion wird der Timeout für das Empfangen von Daten gesetzt.
	 *
 * \param seconds Anzahl Sekunden
 * \param useconds Anzahl Millisekunden
 * \note Diese Funktion hat zur Zeit noch keine Auswirkungen
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	timeout_sec=seconds;
	timeout_usec=useconds;
}
#endif

#ifdef TODO
size_t UDPSocket::sendTo(const String &host, int port, const String &buffer)
/*! \brief UDP-Packet verschicken
 *
 * \header \#include <ppl6.h>
 * \desc
 * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt.
 *
 * \param host Der Name oder die IP-Adresse des Zielrechners
 * \param port Der Port des Zielrechners
 * \param buffer Ein Pointer auf eine String-Klasse, die die zu sendenden Daten enthält
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	return sendTo(host,port,(const void *)buffer.getPtr(),buffer.len());
}




size_t UDPSocket::sendTo(const String &host, int port, const void *buffer, size_t bytes)
/*! \brief UDP-Packet verschicken
 *
 * \header \#include <ppl6.h>
 * \desc
 * Mit dieser Funktion wird ein UDP-Paket an den angegebenen Host verschickt.
 *
 * \param host Der Name oder die IP-Adresse des Zielrechners
 * \param port Der Port des Zielrechners
 * \param buffer Ein Pointer auf den Puffer, der die zu sendenden Daten enthält
 * \param bytes Die Anzahl Bytes im Puffer, die gesendet werden sollen
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gesendeter Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	if (!host) {
		ppl6::SetError(194,"int UDPSocket::SendTo(==> char *host <== , int port, void *buffer, int bytes)");
		return -1;
	}
	if (!port) {
		ppl6::SetError(194,"int UDPSocket::SendTo(char *host, ==> int port <== , void *buffer, int bytes)");
		return -1;
	}
	if (!buffer) {
		ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, ==> void *buffer <== , int bytes)");
		return -1;
	}
	if (bytes<0) {
		ppl6::SetError(194,"int UDPSocket::SendTo(char *host, int port, void *buffer, ==> int bytes <== )");
		return -1;
	}
	ppl6::CAssocArray res, *a;
	ppl6::CBinary *bin;
	if (!ppl6::GetHostByName(host,&res)) return -1;
	a=res.GetFirstArray();
	//a->List();


	int domain, type, protocol;
	domain=ppl6::atoi(a->Get("ai_family"));
	type=ppl6::atoi(a->Get("ai_socktype"));
	//protocol=ppl6::atoi(a->Get("ai_protocol"));
	struct protoent *proto=getprotobyname("UDP");
	if (!proto) {
		ppl6::SetError(395);
		return -1;
	}
	protocol=proto->p_proto;
	bin=a->GetBinary("ai_addr");
	//a->List();
	const struct sockaddr *to=(const struct sockaddr *)bin->GetPtr();
	((sockaddr_in*)to)->sin_port=htons(port);
	PPLSOCKET *s=(PPLSOCKET*)socket;
	if (!s) {
		socket=malloc(sizeof(PPLSOCKET));
		s=(PPLSOCKET*)socket;
		s->sd=-1;
	} else if ((int)s->sd>-1) {
		ppl_closesocket(s->sd);
	}
	s->sd=::socket(domain,SOCK_DGRAM,protocol);
	//sockfd=::socket(AF_INET,SOCK_DGRAM,0);
	if (s->sd<0) {
		SetSocketError();
		return -1;
	}
#ifdef _WIN32
	int ret=::sendto(s->sd,(const char*)buffer,bytes,0,to,bin->GetSize());
#else
	ssize_t ret=::sendto(s->sd,(const void*)buffer,(size_t)bytes,0,to,(socklen_t) bin->GetSize());
#endif
	if (ret<0) {
		printf ("ret: %i\n",(int)ret);
		SetSocketError();
		return -1;
	}
	//close(sockfd);
	return ret;
}



int UDPSocket::RecvFrom(CString &buffer, int maxlen)
/*! \brief UDP-Packet empfangen
 *
 * \header \#include <ppl6.h>
 * \desc
 * Diese Funktion wartet auf ein UDP-Packet
 *
 * \param buffer Ein Pointer auf eine String-Klasse, in die die Daten geschrieben werden sollen
 * \param maxlen Die maximale Anzahl Bytes, die in den Puffer geschrieben werden können
 * \returns Im Erfolgsfall liefert die Funktion die Anzahl gelesener Bytes zurück, im Fehlerfall -1.
 * Der Fehlercode kann über die üblichen Fehler-Funktionen ausgelesen werden
 *
 * \since Wurde mit Version 6.0.19 eingeführt
 */
{
	char *b=(char*)malloc(maxlen+1);
	if (!b) {
		SetError(2);
		return 0;
	}
	int ret=RecvFrom((void*)b,maxlen);
	buffer.ImportBuffer(b,maxlen);
	return ret;
}
Exemplo n.º 19
0
int service_sudo(Connection *Conn,int svsock,int svport){
	int fc;
	int fv[2];
	int rv[2];
	CStr(req,1024);
	CStr(com,1024);
	CStr(arg,1024);
	CStr(a1,1024);
	CStr(a2,1024);
	CStr(a3,1024);
	const char *dp;
	CStr(resp,1024);
	int tsock = -1;
	int clsock;
	int isUDP;
	int rcc;
	int fd;
	CStr(local,MaxHostNameLen);
	CStr(remote,MaxHostNameLen);
	CStr(opts,MaxHostNameLen);
	CStr(clhost,128);
	int clport;

	gethostName(svsock,AVStr(local),"%A");
	sv1log("==SU START uid=%d/%d sock=%d port=%d udp=%d [%s]\n",
		getuid(),geteuid(),svsock,svport,isUDPsock(svsock),local);

	if( svport == 0 ){
		sprintf(local,"%s/sudo/port/P%s",DELEGATE_DGROOT,portSUDO);
		unlink(local);
		svsock = server_open_un("SUDO",AVStr(local),32);
		sv1log("==SU sock[%d] %s\n",svsock,local);
		if( svsock < 0 ){
			return -1;
		}
		if( geteuid() == 0 ){
			int omode = File_mod(local);
			/* set the owner of the socket to the one in OWNER */
			chmodShared(local);
			chmod(local,omode|0660);
		}
	}


	if( isUDP = isUDPsock(svsock) ){
	}else{
	}

	if( isUDP ){
		tsock = server_open_un("SUDO",AVStr(local),32);
		sv1log("---> tsock:%d [%s]\n",tsock,local);
	}else{
		tsock = svsock;
	}

	fc = 1;
	fv[0] = tsock;
	if( 0 <= isPrivateSUDO ){
		fc = 2;
		fv[1] = isPrivateSUDO;
	}

	for(;;){
		/*
		if( PollIn(tsock,0) <= 0 ){
			break;
		}
		*/
		if( PollIns(0,fc,fv,rv) <= 0 ){
			sv1log("==SU EXIT: poll error\n");
			break;
		}
		if( fc == 2 ){
			if( rv[1] ){
				sv1log("==SU EXIT: parent died\n");
				break;
			}
			if( rv[0] == 0 )
				continue;
		}

		clsock = tsock;
		if( !isUDP && !IsConnected(tsock,NULL) ){
			clsock = ACCEPT1(tsock,1,-1,10,AVStr(clhost));
			if( clsock < 0 ){
				msleep(100);
				continue;
			}
		}
		rcc = RecvFrom(clsock,req,sizeof(req)-1,AVStr(clhost),&clport);
		if( rcc <= 0 ){
			sv1log("==SU %d %d rcc=%d\n",tsock,clsock,rcc);
			if( clsock != tsock ){
				close(clsock);
				continue;
			}else{
				sv1log("==SU EXIT: read error\n");
				break;
			}
		}
		setVStrEnd(req,rcc);
		dp = wordScan(req,com);
		if( *dp == ' ' )
			textScan(dp+1,arg);
		else	lineScan(dp,arg);
		dp = wordScan(arg,a1);
		dp = wordScan(dp,a2);
		lineScan(dp,a3);
		sv1log("==SU Q[%s][%s]\n",com,arg);
		putLoadStat(ST_ACC,1);
		putLoadStat(ST_DONE,1);
		put_svstat();
		incRequestSerno(Conn);

		if( strcaseeq(com,"QUIT") ){
			if( isUDP ){
				continue;
			}else{
				sv1log("==SU EXIT: by QUIT command\n");
				break;
			}
		}
		if( strcaseeq(com,"PAM") ){
			doPAM(clsock,clhost,clport,tsock,arg);
			continue;
		}
		if( strcaseeq(com,"BIND") ){
			doBind(clsock,clhost,clport,tsock,arg);
			continue;
		}
/*
		if( strcaseeq(com,"STDERR") ){
			sv1log("==SU receiving @fd[%d]\n",usock);
			fd = recvFd(usock);
 fprintf(stderr,"---- STDERR %d -> %d\n",usock,fd);
			if( 0 <= fd ){
				dup2(fd,fileno(stderr));
 fprintf(stderr,"---- STDERR %d dup2\n",fd);
			}
		}
*/
	}
	return 0;
}
Exemplo n.º 20
0
// UDP listener main loop
void ListenerUDPMainLoop(LISTENER *r)
{
	UCHAR *data;
	// Validate arguments
	if (r == NULL)
	{
		return;
	}

	Debug("ListenerUDPMainLoop Starts.\n");
	r->Status = LISTENER_STATUS_TRYING;

	while (true)
	{
		// Try to listen on the UDP port
		while (true)
		{
			// Stop flag inspection
			if (r->Halt)
			{
				// Stop
				return;
			}

			Debug("NewUDP()\n");
			r->Sock = NewUDP(r->Port);
			if (r->Sock != NULL)
			{
				// Wait success
				break;
			}

			// Wait failure
			Debug("Failed to NewUDP.\n");
			Wait(r->Event, LISTEN_RETRY_TIME);

			// Stop flag inspection
			if (r->Halt)
			{
				Debug("UDP Halt.\n");
				return;
			}
		}

		r->Status = LISTENER_STATUS_LISTENING;
		Debug("Start Listening at UDP Port %u.\n", r->Sock->LocalPort);

		// Stop flag inspection
		if (r->Halt)
		{
			// Stop
			goto STOP;
		}

		// Allocate the buffer area
		data = Malloc(UDP_PACKET_SIZE);

		// Read the next packet
		while (true)
		{
			IP src_ip;
			UINT src_port;
			UINT size;
			SOCKSET set;

			InitSockSet(&set);
			AddSockSet(&set, r->Sock);
			Select(&set, SELECT_TIME, NULL, NULL);

			size = RecvFrom(r->Sock, &src_ip, &src_port, data, UDP_PACKET_SIZE);
			if (((size == 0) && (r->Sock->IgnoreRecvErr == false)) || r->Halt)
			{
				// Error has occurred
STOP:
				Disconnect(r->Sock);
				ReleaseSock(r->Sock);
				r->Sock = NULL;
				Debug("UDP Listen Stopped.\n");
				Free(data);
				break;
			}

			// Received an UDP packet
			if (size != SOCK_LATER)
			{
				UDPReceivedPacket(r->Cedar, r->Sock, &src_ip, src_port, data, size);
			}
		}
	}
}