PING.C

/****************************************************************************\ 
* ping.c -- sample program demonstrating NWLink.
*
* Microsoft Developer Support
* Copyright 1992 - 1998 Microsoft Corporation
*
* This program is a simple example of opening a socket,
* binding to the socket, receiving a packet and sending
* that packet back to the original sender.
*
****************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <wsipx.h>
#include <wsnwlink.h>
#include "../testlib/testlib.h"

/*
* Sockaddr structures
*/

SOCKADDR_IPX addr;
SOCKADDR_IPX baddr;
SOCKADDR_IPX raddr;
int addrlen;

/*
* Function Prototypes
*/

extern int main(int, char **);
extern int net_init(SOCKET *);
extern int do_ping(SOCKET);

/****************************************************************************
*
* FUNCTION: main( int argc, char **argv )
*
* PURPOSE: This is the main entry for the program
*
*
* ARGUMENTS:argc = Number of arguments
* argv = Array of ptrs to cmd line args
*
*
* RETURNS: Exit code for the program
*
*\***************************************************************************/
int main(int argc, char **argv)
{
SOCKET s;

/*
* Set our default values before calling parse_cmd_line
*/

*Local_Socket_Number = 0x30;
*(Local_Socket_Number+1) = 0x00;
Receive_Length = 2048;

/*
* Get any command line options
*/

parse_cmd_line(argc, argv);

/*
* Initialize the network and set up our socket
*/

if (net_init(&s))
return 1;

do_ping(s);

/*
* All done (We only get here on error)
*/

if (verbose)
printf("calling closesocket()");

closesocket(s);
return 0;
}

/****************************************************************************
*
* FUNCTION: net_init( SOCKET *skt )
*
* PURPOSE: Initializes the WinSock stuff and sets up our socket.
*
*
* ARGUMENTS:SOCKET * => struct to receive our socket info
*
* RETURNS: 0 if ok
*1 if error
*
*\***************************************************************************/
int net_init(SOCKET *skt)
{
int rc, addrlen;
WSADATA wsdata;
SOCKET s;
WORD wVersionRequested;

/*
* Initialize with the WINSOCK library
*/

if (verbose)
printf("calling WSAStartup(), ");

wVersionRequested = MAKEWORD(1,1);
rc = WSAStartup(wVersionRequested, &wsdata);

if (verbose)
printf("return = 0x%X (%d)\n", rc, rc);

if (rc) {
printf("WSAStartup failed: error code = %d\n", rc);
return 1;
}

if (verbose) {
printf("contents of wsdata struct: \n");
print_wsa(&wsdata);
}

if (verbose)
printf("calling socket(address family = %d, socket type = %d, protocol = %d)\n", Local_Address_Family, Socket_Type, Protocol);

/*
* Open a DATAGRAM socket with IPX
*/

s = socket(AF_NS, SOCK_DGRAM, NSPROTO_IPX);

if (verbose)
printf("socket() returned 0x%lX\n", s);

if (s == INVALID_SOCKET) {
dos_net_perror("Socket call failed");
exit(1);
}

/*
* Bind to a socket. We want to bind to a well known
* socket so that the app. that sends us a packet will
* know where to send it.
*/

addr.sa_family = Local_Address_Family;

memcpy(&addr.sa_netnum, Local_Network_Number, 4);
memcpy(&addr.sa_nodenum, Local_Node_Number, 6);
memcpy(&addr.sa_socket, Local_Socket_Number, 2);

if (verbose) {
printf("calling bind():\n ");
print_saddr(&addr);
}

rc = bind(s, (const struct sockaddr *) &addr, 16);

if (verbose)
printf("bind() returned 0x%X\n", rc);

if (rc == SOCKET_ERROR) {
dos_net_perror("Error binding to socket");
closesocket(s);
return 1;
}
/*
* Set the packet type for this socket
*/

if (verbose)
printf("Calling setsockopt for packet type %d\n", Local_Packet_Type);

rc = setsockopt(s, SOL_SOCKET, IPX_PTYPE, (const char *) &Local_Packet_Type, 4);

if (rc == SOCKET_ERROR)
dos_net_perror("setsockopt() call failed");


/*
* Get the address we bound to and print it out
*/

if (verbose)
printf("Calling getsockname(socket = %d), ");

addrlen = 16;
rc = getsockname(s, (struct sockaddr *) &baddr, &addrlen);

if (verbose)
printf("return = 0x%X (%d)\n", rc, rc);

if (rc == SOCKET_ERROR) {
dos_net_perror("Error getting socket name");
closesocket(s);
return 1;
}

/*
* Print out the network address
*/

if (verbose) {
printf("addrlen = %d\n", addrlen);
print_netaddr(baddr.sa_netnum, "Bound address = ", "\n");
}

if (verbose)
printf("Allocating %d byte receive buffer\n", Receive_Length);

/*
* Set up socket to send back
*/

*skt = s;

return 0;
}

/****************************************************************************
*
* FUNCTION: do_ping( SOCKET s )
*
* PURPOSE: This will receive a packet then send it back.
*
* ARGUMENTS:SOCKET socket we are transmitting on.
*
* RETURNS: 0 if ok
*1 if error
*
*\***************************************************************************/
int do_ping(SOCKET s)
{
LPSTR recvbuf;
int nbytes, rc, errflag = 0;
int rcvpkts = 0, sndpkts = 0;

/*
* Allocate a buffer for receives
*/

recvbuf = malloc(Receive_Length);

if (!recvbuf) {
printf("Error allocating %d bytes for receive buffer\n", Receive_Length);
return 1;
}

/*
* This loop will receive a packet and then send
* it back to whoever sent it to us.
*
* To exit the loop - hit CTRL-C.
*/

while (1) {

/*
* Recv a packet
*/

/*
* NOTE: If you want to know the packet type field of the
* packet you just received, look at the byte at
* raddr.sa_ptype. The addrlen returned will be
* 15.
*
* By using the addrlen field unchanged when sending
* the packet back, you will send the packet back with
* the same packet type that is was sent with originally
*/

addrlen = 16;

if (verbose)
printf("calling recvfrom(socket = %d, len = %d)\n", s, Receive_Length);

nbytes = recvfrom(s, recvbuf, Receive_Length, 0, (struct sockaddr *) &raddr, &addrlen);

/*
* If error - print it and exit
*/

if (nbytes == SOCKET_ERROR) {
dos_net_perror("recvfrom() failed");
errflag++;
break;
}

if (verbose) {
printf("received %d bytes, raddr = \n ", nbytes);
print_saddr(&raddr);
}

if (!verbose)
printf("\rRecv packet number %d", ++rcvpkts);

/*
* Send the data back
*/

if (verbose)
printf("calling sendto(socket = %d, len = %d\n", s, nbytes);

addrlen = 16;
rc = sendto(s, recvbuf, nbytes, 0, (const struct sockaddr *) &raddr, addrlen);

if (verbose)
printf("sendto() returned 0x%X\n", rc);

if (rc == SOCKET_ERROR) {
dos_net_perror("sendto() failed");
errflag++;
break;
}

if (!verbose)
printf(" : Send packet number %d", ++sndpkts);

}

if (verbose)
printf("Freeing receive buffer\n");

free(recvbuf);

return errflag;
}