Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

313 lines
7.2 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Relagnt.c
Abstract:
Simple BOOTP relay agent.
Author:
David Treadwell (davidtr) 18-Aug-1993
Revision History:
--*/
#define FD_SETSIZE 1000
#include <stdio.h>
#include <stdlib.h>
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winsock.h>
#include <dhcp.h>
WSADATA WsaData;
#define BOOTP_SERVER_PORT htons(67)
#define BOOTP_CLIENT_PORT htons(68)
DWORD Mask1;
DWORD IpAddr1;
DWORD Subnet1;
DWORD BroadcastIpAddr1;
DWORD Mask2;
DWORD IpAddr2;
DWORD Subnet2;
DWORD BroadcastIpAddr2;
VOID
ProcessBootpDatagram (
IN SOCKET ReceiveSocket,
IN DWORD ReceiveAddress,
IN DWORD ReceiveBroadcastAddress,
IN SOCKET OtherSocket,
IN DWORD OtherBroadcastAddress
);
void _CRTAPI1
main (
int argc,
char *argv[]
)
{
INT err;
SOCKADDR_IN addr;
SOCKET net1Socket;
SOCKET net2Socket;
FD_SET readfds;
INT one = 1;
err = WSAStartup( 0x0101, &WsaData );
if ( err == SOCKET_ERROR ) {
return;
}
//
// Read the command line parameters: two sets of a subnet mask and
// subnet value.
//
if ( argc != 5 ) {
printf( "usage: relagnt mask1 addr1 mask2 addr2\n" );
return;
}
Mask1 = inet_addr( argv[1] );
IpAddr1 = inet_addr( argv[2] );
Subnet1 = Mask1 & IpAddr1;
BroadcastIpAddr1 = Subnet1 | ~Mask1;
Mask2 = inet_addr( argv[3] );
IpAddr2 = inet_addr( argv[4] );
Subnet2 = Mask2 & IpAddr2;
BroadcastIpAddr2 = Subnet2 | ~Mask2;
//
// Open and bind the socket for the server BOOTP port on the first
// network.
//
net1Socket = socket( AF_INET, SOCK_DGRAM, 0 );
if ( net1Socket == INVALID_SOCKET ) {
printf( "socket() failed for net1Socket: %ld\n", WSAGetLastError( ) );
return;
}
RtlZeroMemory( &addr, sizeof(addr) );
addr.sin_family = AF_INET;
addr.sin_port = BOOTP_SERVER_PORT;
addr.sin_addr.s_addr = IpAddr1;
err = bind( net1Socket, (PSOCKADDR)&addr, sizeof(addr) );
if ( err < 0 ) {
printf( "bind() failed for net1Socket: %ld\n", WSAGetLastError( ) );
}
//
// Allow broadcasting on the socket.
//
err = setsockopt( net1Socket, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof(one) );
if ( err < 0 ) {
printf( "setsockopt() failed for net1Socket: %ld\n", WSAGetLastError( ) );
}
//
// Open and bind the socket for the server BOOTP port on the second
// network.
//
net2Socket = socket( AF_INET, SOCK_DGRAM, 0 );
if ( net2Socket == INVALID_SOCKET ) {
printf( "socket() failed for net2Socket: %ld\n", WSAGetLastError( ) );
return;
}
RtlZeroMemory( &addr, sizeof(addr) );
addr.sin_family = AF_INET;
addr.sin_port = BOOTP_SERVER_PORT;
addr.sin_addr.s_addr = IpAddr2;
err = bind( net2Socket, (PSOCKADDR)&addr, sizeof(addr) );
if ( err < 0 ) {
printf( "bind() failed for net2Socket: %ld\n", WSAGetLastError( ) );
}
//
// Allow broadcasting on the socket.
//
err = setsockopt( net2Socket, SOL_SOCKET, SO_BROADCAST, (char *)&one, sizeof(one) );
if ( err < 0 ) {
printf( "setsockopt() failed for net2Socket: %ld\n", WSAGetLastError( ) );
}
//
// Loop receiving and processing BOOTP datagrams.
//
while ( TRUE ) {
FD_ZERO( &readfds );
FD_SET( net1Socket, &readfds );
FD_SET( net2Socket, &readfds );
err = select( 4, &readfds, NULL, NULL, NULL );
if ( err < 0 ) {
printf( "select() failed: %ld\n", WSAGetLastError( ) );
}
if ( err == 0 ) {
printf( "select() returned 0 handles ready.\n" );
continue;
}
if ( FD_ISSET( net1Socket, &readfds ) ) {
//
// Process this message.
//
ProcessBootpDatagram(
net1Socket,
IpAddr1,
BroadcastIpAddr1,
net2Socket,
BroadcastIpAddr2
);
}
if ( FD_ISSET( net2Socket, &readfds ) ) {
//
// Process this message.
//
ProcessBootpDatagram(
net2Socket,
IpAddr2,
BroadcastIpAddr2,
net1Socket,
BroadcastIpAddr1
);
}
}
} // main
VOID
ProcessBootpDatagram (
IN SOCKET ReceiveSocket,
IN DWORD ReceiveAddress,
IN DWORD ReceiveBroadcastAddress,
IN SOCKET OtherSocket,
IN DWORD OtherBroadcastAddress
)
{
SOCKADDR_IN addr;
INT err;
BYTE ioBuffer[4096];
DWORD fromaddr;
PDHCP_MESSAGE dhcpMessage;
INT messageLength;
INT addrLength;
SOCKET sendSocket;
//
// Receive the datagram.
//
addrLength = sizeof(addr);
err = recvfrom(
ReceiveSocket,
ioBuffer,
sizeof(ioBuffer),
0,
(PSOCKADDR)&addr,
&addrLength
);
if ( err < 0 ) {
printf( "recvfrom() on socket %lx failed: %ld\n", ReceiveSocket, WSAGetLastError( ) );
return;
}
fromaddr = addr.sin_addr.s_addr;
dhcpMessage = (PDHCP_MESSAGE)ioBuffer;
messageLength = err;
//
// If this is a message that we sent, do not forward it.
//
if ( fromaddr == IpAddr1 || fromaddr == IpAddr2 ) {
return;
}
//
// Only put our address in the gateway agent address field of the
// message if there is not already an address in that field. If
// there is already an address in that field, then another relay
// agent is acting as the "primary" relay agent.
//
if ( dhcpMessage->RelayAgentIpAddress == 0 ) {
dhcpMessage->RelayAgentIpAddress = ReceiveAddress;
}
//
// Determine the IP address and port we'll send the datagram to. If
// we got the datagram from a server, then we'll broadcast it the
// same interface it came in on but to the client port. If we got
// it from a client, broadcast it to servers on the other interface.
//
if ( addr.sin_port == BOOTP_CLIENT_PORT ) {
addr.sin_addr.s_addr = OtherBroadcastAddress;
addr.sin_port = BOOTP_SERVER_PORT;
sendSocket = OtherSocket;
} else if ( addr.sin_port == BOOTP_SERVER_PORT ) {
addr.sin_addr.s_addr = INADDR_BROADCAST;
addr.sin_port = BOOTP_CLIENT_PORT;
sendSocket = ReceiveSocket;
} else {
printf( "received BOOTP datagram from invalid port %ld\n",
ntohs( addr.sin_port ) );
}
printf( "forwarding BOOTP dg from %s ",
inet_ntoa( *(PIN_ADDR)&fromaddr ) );
printf( "to %s port %ld\n",
inet_ntoa( addr.sin_addr ), ntohs( addr.sin_port ) );
//
// Broadcast the response on the other net.
//
err = sendto(
sendSocket,
ioBuffer,
messageLength,
0,
(PSOCKADDR)&addr,
sizeof(addr)
);
if ( err < 0 ) {
printf( "sendto() on socket %lx failed: %ld\n", sendSocket, WSAGetLastError( ) );
return;
}
return;
} // ProcessBootpDatagram