Ejemplo n.º 1
0
/** Processes an IP packet inside an Ethernet frame, and writes the appropriate response
 *  to the output Ethernet frame if one is created by a sub-protocol handler.
 *
 *  \param[in] InDataStart    Pointer to the start of the incoming packet's IP header
 *  \param[out] OutDataStart  Pointer to the start of the outgoing packet's IP header
 *
 *  \return The number of bytes written to the out Ethernet frame if any, NO_RESPONSE if no
 *           response was generated, NO_PROCESS if the packet processing was deferred until the
 *           next Ethernet packet handler iteration
 */
int16_t IP_ProcessIPPacket(void* InDataStart,
                           void* OutDataStart)
{
	DecodeIPHeader(InDataStart);

	IP_Header_t* IPHeaderIN  = (IP_Header_t*)InDataStart;
	IP_Header_t* IPHeaderOUT = (IP_Header_t*)OutDataStart;

	/* Header length is specified in number of longs in the packet header, convert to bytes */
	uint16_t HeaderLengthBytes = (IPHeaderIN->HeaderLength * sizeof(uint32_t));

	int16_t  RetSize = NO_RESPONSE;

	/* Check to ensure the IP packet is addressed to the virtual webserver's IP or the broadcast IP address */
	if (!(IP_COMPARE(&IPHeaderIN->DestinationAddress, &ServerIPAddress)) &&
	    !(IP_COMPARE(&IPHeaderIN->DestinationAddress, &BroadcastIPAddress)))
	{
		return NO_RESPONSE;
	}

	/* Pass off the IP payload to the appropriate protocol processing routine */
	switch (IPHeaderIN->Protocol)
	{
		case PROTOCOL_ICMP:
			RetSize = ICMP_ProcessICMPPacket(&((uint8_t*)InDataStart)[HeaderLengthBytes],
			                                 &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]);
			break;
		case PROTOCOL_TCP:
			RetSize = TCP_ProcessTCPPacket(InDataStart,
			                               &((uint8_t*)InDataStart)[HeaderLengthBytes],
			                               &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]);
			break;
		case PROTOCOL_UDP:
			RetSize = UDP_ProcessUDPPacket(InDataStart,
			                               &((uint8_t*)InDataStart)[HeaderLengthBytes],
			                               &((uint8_t*)OutDataStart)[sizeof(IP_Header_t)]);
			break;
	}

	/* Check to see if the protocol processing routine has filled out a response */
	if (RetSize > 0)
	{
		/* Fill out the response IP packet header */
		IPHeaderOUT->TotalLength        = SwapEndian_16(sizeof(IP_Header_t) + RetSize);
		IPHeaderOUT->TypeOfService      = 0;
		IPHeaderOUT->HeaderLength       = (sizeof(IP_Header_t) / sizeof(uint32_t));
		IPHeaderOUT->Version            = 4;
		IPHeaderOUT->Flags              = 0;
		IPHeaderOUT->FragmentOffset     = 0;
		IPHeaderOUT->Identification     = 0;
		IPHeaderOUT->HeaderChecksum     = 0;
		IPHeaderOUT->Protocol           = IPHeaderIN->Protocol;
		IPHeaderOUT->TTL                = DEFAULT_TTL;
		IPHeaderOUT->SourceAddress      = IPHeaderIN->DestinationAddress;
		IPHeaderOUT->DestinationAddress = IPHeaderIN->SourceAddress;

		IPHeaderOUT->HeaderChecksum     = Ethernet_Checksum16(IPHeaderOUT, sizeof(IP_Header_t));

		/* Return the size of the response so far */
		return (sizeof(IP_Header_t) + RetSize);
	}

	return RetSize;
}
Ejemplo n.º 2
0
//
// Function: main
//
// Description:
//    This function loads Winsock, parses the command line, and
//    begins receiving packets. Once a packet is received they
//    are decoded. Because we are receiving IP datagrams, the
//    receive call will return whole datagrams.
//
int __cdecl main(int argc, char **argv)
{
    SOCKET        s = INVALID_SOCKET;
    WSADATA       wsd;
    WSABUF        wbuf = {0};
    DWORD         dwBytesRet = 0, dwFlags = 0;
    char         *rcvbuf=NULL;
    int           rc = 0, err;

    //
    // Load Winsock
    //
    if ((rc = WSAStartup(MAKEWORD(2,2), &wsd)) != 0)
    {
        printf("WSAStartup() failed: %d\n", rc);
        return -1;
    }

    //
    // Parse the command line
    //
    if (ValidateArgs(argc, argv) == SOCKET_ERROR)
    {
        usage(argv[0]);
    }

    if ( g_ulFilterMask & (FILTER_MASK_SOURCE_ADDRESS | FILTER_MASK_SOURCE_PORT) )
    {
        printf("Source address filter     : ");
        PrintAddress((SOCKADDR *)&g_saSourceAddress, sizeof(g_saSourceAddress));
        printf("\n");
    }
    if ( g_ulFilterMask & (FILTER_MASK_DESTINATION_ADDRESS | FILTER_MASK_DESTINATION_PORT) )
    {
        printf("Destination address filter: ");
        PrintAddress((SOCKADDR *)&g_saDestinationAddress, sizeof(g_saDestinationAddress));
        printf("\n");
    }

    //
    // Create a raw socket for receiving IP datagrams
    //
    s = WSASocket(g_saLocalInterface.ss_family, SOCK_RAW, g_dwProtocol, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (s == INVALID_SOCKET)
    {
        printf("WSASocket() failed: %d\n", WSAGetLastError());
        return -1;
    }

    //
    // This socket MUST be bound before calling the ioctl
    //
    rc = bind(s, (SOCKADDR *)&g_saLocalInterface, sizeof(g_saLocalInterface));
    if (rc == SOCKET_ERROR)
    {
        printf("bind() failed: %d\n", WSAGetLastError());
        if (INVALID_SOCKET != s)
        {
            closesocket(s);
            s = INVALID_SOCKET;
        }
        WSACleanup();
        return -1;
    }
    printf("Binding to: ");
    PrintAddress((SOCKADDR *)&g_saLocalInterface, sizeof(g_saLocalInterface));
    printf("\n");

    //
    // Set the SIO_RCVALLxxx ioctl
    //
    rc = WSAIoctl(s, g_dwIoControlCode, &g_dwIoControlValue, sizeof(g_dwIoControlValue),
                  NULL, 0, &dwBytesRet, NULL, NULL);
    if (rc == SOCKET_ERROR)
    {
        printf("WSAIotcl(0x%x) failed: %d\n", g_dwIoControlCode,
               (err = WSAGetLastError()));
        if (err == WSAEINVAL)
        {
            printf("NOTE: IPv6 does not currently support the SIO_RCVALL* ioctls\n");
        }

        if (INVALID_SOCKET != s)
        {
            closesocket(s);
            s = INVALID_SOCKET;
        }
        WSACleanup();
        return -1;
    }

    //
    // Allocate a buffer for receiving data
    //
    rcvbuf = (char *)HeapAlloc(GetProcessHeap(), 0, MAX_IP_SIZE);
    if (rcvbuf == NULL)
    {
        fprintf(stderr, "HeapAlloc failed: %d\n", GetLastError());
        if (INVALID_SOCKET != s)
        {
            closesocket(s);
            s = INVALID_SOCKET;
        }
        WSACleanup();
        return -1;
    }

    //
    // Start receiving IP datagrams until interrupted
    // 
    while (1)
    {
        wbuf.len = MAX_IP_SIZE;
        wbuf.buf = rcvbuf;
        dwFlags  = 0;

        rc = WSARecv(s, &wbuf, 1, &dwBytesRet, &dwFlags, NULL, NULL);
        if (rc == SOCKET_ERROR)
        {
            printf("WSARecv() failed: %d\n", WSAGetLastError());
            break;
        }
        // Decode the IP header
        //
        rc = DecodeIPHeader(
                           rcvbuf,
                           dwBytesRet, 
                           g_ulFilterMask,
                           (SOCKADDR *)&g_saSourceAddress,
                           (SOCKADDR *)&g_saDestinationAddress
                           );
        if (rc != NO_ERROR)
        {
            printf("Error decoding IP header!\n");
            break;
        }
    }
    //
    // Cleanup
    //

    if (rcvbuf) HeapFree(GetProcessHeap(), 0, rcvbuf);

    if (INVALID_SOCKET != s)
    {
        closesocket(s);
        s = INVALID_SOCKET;
    }
    WSACleanup();

    return 0;
}