PROGRAM 3
/****************************************************************************/
/* program: mypdrive.c */
/* author: anthony f. ortiz */
/* class: cs3590 */
/* date: march 11, 1999 */
/* description: packet driver program */
/****************************************************************************/
#include
#include
#include
#include "pktdrive.h"
#define ADDRESS_LEN 6
#define MAX_PACKET_LEN 1518
/* receiver for access function. */
int far my_receiver(void);
/* print ethernet address menu. */
void print_menu ();
/* choose a ethernet destination address. */
char get_destination ();
/* get the ethernet source address from a packet. */
void get_source ();
/* get the string that will be sent to the ethernet destination address. */
void get_string ();
/* construct the packet. */
void construct_packet ();
/* construct a packet for the reversed string. */
void construct_rpacket ();
/* print the string. */
void print_packet (char in_buf [], int in_len);
/* print the reversed string */
void print_rpacket (char in_buf [], int in_len);
/* reverse the string and display it on the screen. */
void reverse_string (char in_buf [], int in_len);
int intno = 126;
int the_handle = 0;
int the_version;
int if_class;
int if_type;
int if_number;
int if_basic;
char typeptr[] = {0x08, 0x01};
int typeln = 2;
char address_buf[ADDRESS_LEN];
int in_len;
static char in_buf[MAX_PACKET_LEN];
static the_flag=0, the_count=0;
char the_out_packet[MAX_PACKET_LEN] = {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', };
char data [MAX_PACKET_LEN];
char source [ADDRESS_LEN];
char destination [ADDRESS_LEN];
char choice [ADDRESS_LEN];
main()
{
char ch;
int key;
clrscr ();
/* test for packet driver. */
if (!test_for_pd(intno))
{
printf("No Packet Driver at interrupt %d\n", intno);
exit(1);
}
/* get driver information. */
driver_info(intno, the_handle,
&the_version, &if_class, &if_type, &if_number, &if_basic);
/* make access to packets of all types. */
the_handle = access_type(intno, if_class, ANYTYPE, 0,
typeptr, typeln, my_receiver);
/* get the ethernet source address. */
get_address(intno, the_handle, address_buf, ADDRESS_LEN);
/* print the ethernet address menu. */
print_menu ();
key = 0;
choice [0] = 0xff;
/* perform client/server functions until key = t. */
do
{
/* test for key stroke. */
key = kbhit ();
/* if key has been hit, get destination address, get string, */
/* construct the packet, and send it. */
if (key != 0)
{
/* get ethernet destination address. */
ch = get_destination ();
/* get the string that will be sent to the ethernet */
/* destination address. */
get_string ();
/* construct the packet. */
construct_packet ();
/* send the packet. */
send_pkt (intno, the_out_packet, 70);
}
/* if count > 0, perform if statement. */
if (the_count > 0)
{
the_count = 0;
/* get the ethernet source address from a packet. */
get_source ();
/* if source <> to choice, then print the string, reverse */
/* the string and print it, construct a packet for the */
/* reversed string, and send it. otherwise, print the */
/* reversed string. */
if (strcmp (source, choice) != 0)
{
/* print the string. */
print_packet (in_buf, in_len);
/* reverse the string. */
reverse_string (in_buf, in_len);
/* construct a packet for the reversed string. */
construct_rpacket ();
/* send the packet. */
send_pkt (intno, the_out_packet, 70);
}
else
{
/* print the reversed string. */
print_rpacket (in_buf, in_len);
choice [0] = 0xff;
}
}
} while (ch != 't');
/* end access of packets associated with the handle. */
release_type(intno, the_handle);
return(0);
}
/*****************************************************************/
/* my_receiver - called by the packet driver twice for each */
/* packet. */
/*****************************************************************/
int far my_receiver(void)
{
unsigned int save_ax;
asm {
push ds;
push di;
cli; /* no interrupts please. */
mov save_ax,ax;
mov ax,seg in_buf;
mov ds,ax;
}
if (save_ax == 0)
{
asm { /* return with es:di -> in_buf. */
mov ax,ds;
mov es,ax; /* es gets the segment address. */
mov ax,offset in_buf;
mov [bp-4],ax; /* di gets the offset. */
mov in_len,cx; /* the length of the packet was in cx. */
}
}
else the_count++;
asm {
pop di;
pop ds;
}
return 0;
}
/* print the ethernet address menu. */
void print_menu ()
{
gotoxy (1, 1);
cprintf ("ethernet address menu");
gotoxy (5, 3);
cprintf ("a. 00.20.af.d8.3c.c0");
gotoxy (5, 4);
cprintf ("b. 00.20.af.e4.c9.ff");
gotoxy (5, 5);
cprintf ("c. 00.20.af.4e.c9.f4");
gotoxy (5, 6);
cprintf ("d. 00.20.af.d8.3c.cc");
gotoxy (5, 7);
cprintf ("e. 00.20.af.e4.c9.c5");
gotoxy (5, 8);
cprintf ("f. 00.20.af.e4.c9.d3");
gotoxy (5, 9);
cprintf ("g. 00.20.af.e4.ca.23");
gotoxy (5, 10);
cprintf ("h. 00.20.af.e4.c9.b8");
gotoxy (5, 11);
cprintf ("i. 00.20.af.e4.c9.cf");
gotoxy (5, 12);
cprintf ("j. 00.20.af.e4.c9.b9");
gotoxy (5, 13);
cprintf ("k. 00.20.af.e4.ca.19");
gotoxy (5, 14);
cprintf ("l. 00.20.af.e4.c9.83");
gotoxy (1, 16);
cprintf ("choose one of the above options: ");
gotoxy (1, 18);
cprintf ("send string (locally): ");
gotoxy (1, 19);
cprintf ("receive string (locally): ");
gotoxy (1, 20);
cprintf ("-------------------------------------------------------------------------------");
gotoxy (1, 21);
cprintf ("send string (remotely): ");
gotoxy (1, 22);
cprintf ("receive string (remotely): ");
gotoxy (35, 16);
}
/* get the ethernet destination address. */
char get_destination ()
{
char ch;
gotoxy (35, 16);
ch = getch ();
destination [0] = 0x00;
destination [1] = 0x20;
destination [2] = 0xaf;
if (ch == 'a')
{
destination [3] = 0xd8;
destination [4] = 0x3c;
destination [5] = 0xc0;
}
else if (ch == 'b')
{
destination [3] = 0xe4;
destination [4] = 0xc9;
destination [5] = 0xff;
}
else if (ch == 'c')
{
destination [3] = 0x4e;
destination [4] = 0xc9;
destination [5] = 0xf4;
}
else if (ch == 'd')
{
destination [3] = 0xd8;
destination [4] = 0x3c;
destination [5] = 0xcc;
}
else if (ch == 'e')
{
destination [3] = 0xe4;
destination [4] = 0xc9;
destination [5] = 0xc5;
}
else if (ch == 'f')
{
destination [3] = 0xe4;
destination [4] = 0xc9;
destination [5] = 0xd3;
}
else if (ch == 'g')
{
destination [3] = 0xe4;
destination [4] = 0xca;
destination [5] = 0x23;
}
else if (ch == 'h')
{
destination [3] = 0xe4;
destination [4] = 0xc9;
destination [5] = 0xb8;
}
else if (ch == 'i')
{
destination [3] = 0xe4;
destination [4] = 0xc9;
destination [5] = 0xcf;
}
else if (ch == 'j')
{
destination [3] = 0xe4;
destination [4] = 0xc9;
destination [5] = 0xb9;
}
else if (ch == 'k')
{
destination [3] = 0xe4;
destination [4] = 0xca;
destination [5] = 0x19;
}
else if (ch == 'l')
{
destination [3] = 0xe4;
destination [4] = 0xc9;
destination [5] = 0x83;
}
memcpy (choice, destination, 6);
return ch;
}
/* get the ethernet source address from a packet. */
void get_source ()
{
memcpy (source, in_buf + 6, 6);
}
/* get the string that will be sent to the ethernet destination address. */
void get_string ()
{
gotoxy (27, 18);
cprintf (" ");
gotoxy (27, 18);
gets (data);
gotoxy (35, 16);
}
/* construct the packet. */
void construct_packet ()
{
memcpy (the_out_packet, destination, 6);
memcpy (the_out_packet + 6, address_buf, 6);
the_out_packet [12] = 0x08;
the_out_packet [13] = 0x01;
memcpy (the_out_packet + 14, data, strlen (data));
}
/* construct a packet for the reversed string. */
void construct_rpacket ()
{
memcpy (the_out_packet, in_buf + 6, 6);
memcpy (the_out_packet + 6, in_buf, 6);
the_out_packet [12] = 0x08;
the_out_packet [13] = 0x01;
memcpy (the_out_packet + 14, data, strlen (data));
}
/* print the string. */
void print_packet (char in_buf [], int in_len)
{
int i;
gotoxy (27, 22);
cprintf (" ");
gotoxy (27, 22);
for (i=14; i< in_len; i++)
{
if (in_buf [i] == '[')
break;
cprintf("%c", in_buf[i] & 0xff);
}
gotoxy (35, 16);
}
/* print the reversed string. */
void print_rpacket (char in_buf [], int in_len)
{
int i;
gotoxy (27, 19);
cprintf (" ");
gotoxy (27, 19);
for (i=14; i< in_len; i++)
{
if (in_buf [i] == '[' || in_buf [i] == 13)
break;
cprintf("%c", in_buf[i] & 0xff);
}
gotoxy (35, 16);
}
/* reverse the string and display it on the screen. */
void reverse_string (char in_buf [], int in_len)
{
int i;
char str [80];
char reverse [80];
gotoxy (27, 21);
cprintf (" ");
gotoxy (27, 21);
for (i=14; i< in_len; i++)
{
if (in_buf [i] == '[' || in_buf == 13)
break;
str [i - 14] = in_buf [i] & 0xff;
}
str [i - 14] = '\0';
for (i = 0; i < strlen (str); i++)
{
reverse [i] = str [strlen (str) - 1 - i];
}
reverse [i] = '\0';
strcat (reverse, "[cr]");
cprintf ("%s", reverse);
memcpy (data, reverse, strlen (reverse));
gotoxy (35, 16);
}
/* i didn't write pktdrive.h or pktdrive.c. */
/******************************************************************/
/* pktdrive.h */
/* */
/* clm 2/6/96 */
/******************************************************************/
/* packet driver interface classes */
#define CL_NONE 0
#define CL_ETHERNET 1
#define CL_PRONET_10 2
#define CL_IEEE8025 3
#define CL_OMNINET 4
#define CL_APPLETALK 5
#define CL_SERIAL_LINE 6
#define CL_STARLAN 7
#define CL_ARCNET 8
#define CL_AX25 9
#define CL_KISS 10
#define CL_IEEE8023 11
#define CL_FDDI 12
#define CL_INTERNET_X25 13
#define CL_LANSTAR 14
#define CL_SLFP 15
#define CL_NETROM 16
#define NCLASS 17
/* packet driver interface types (not a complete list) */
#define TC500 1
#define PC2000 10
#define WD8003 14
#define PC8250 15
#define ANYTYPE 0xffff
/* packet driver function call numbers. from appendix b. */
#define DRIVER_INFO 1
#define ACCESS_TYPE 2
#define RELEASE_TYPE 3
#define SEND_PKT 4
#define TERMINATE 5
#define GET_ADDRESS 6
#define RESET_INTERFACE 7
#define GET_PARAMETERS 10
#define AS_SEND_PKT 11
#define SET_RCV_MODE 20
#define GET_RCV_MODE 21
#define SET_MULTICAST_LIST 22
#define GET_MULTICAST_LIST 23
#define GET_STATISTICS 24
#define SET_ADDRESS 25
/* packet driver error return codes. from appendix c. */
#define NO_ERROR 0
#define BAD_HANDLE 1 /* invalid handle number */
#define NO_CLASS 2 /* no interfaces of specified class found */
#define NO_TYPE 3 /* no interfaces of specified type found */
#define NO_NUMBER 4 /* no interfaces of specified number found */
#define BAD_TYPE 5 /* bad packet type specified */
#define NO_MULTICAST 6 /* this interface does not support multicast */
#define CANT_TERMINATE 7 /* this packet driver cannot terminate */
#define BAD_MODE 8 /* an invalid receiver mode was specified */
#define NO_SPACE 9 /* operation failed because of insufficient space */
#define TYPE_INUSE 10 /* the type had previously been accessed, and not released */
#define BAD_COMMAND 11 /* the command was out of range, or not implemented */
#define CANT_SEND 12 /* the packet couldn't be sent (usually hardware error) */
#define CANT_SET 13 /* hardware address couldn't be changed (> 1 handle open) */
#define BAD_ADDRESS 14 /* hardware address has bad length or format */
#define CANT_RESET 15 /* couldn't reset interface (> 1 handle open) */
#define uchar(x) ((unsigned char)(x))
int driver_info(int intno,
int the_handle,
int *the_version,
int *if_class,
int *if_type,
int *if_number,
int *if_basic);
int access_type(int intno,
int if_class,
int if_type,
int if_number,
char *type,
unsigned typelen,
int far (*receiver)());
int release_type(int intno,
int handle);
int get_address(int intno,
int handle,
char *buf,
int len);
int get_parameters(int intno);
int send_pkt(int intno,
char *buffer,
unsigned length);
int test_for_pd(unsigned int intno);
/******************************************************************/
/* pktdrive.c - c interface to packet driver */
/* */
/* clm 5/1/93 derived from phil karn's pktdrvr.c. */
/* clm 2/7/96 revised the call back prototyping. */
/******************************************************************/
#include
#include
#include "pktdrive.h"
static int Derr;
static char Pkt_sig[] = "PKT DRVR"; /* packet driver signature */
/******************************************************************/
/* driver_info - returns information about the interface. */
/* earlier versions of the packet specifications */
/* require "handle" which is returned by the */
/* function "access_type()". */
/******************************************************************/
int driver_info(int intno,
int the_handle,
int *the_version,
int *if_class,
int *if_type,
int *if_number,
int *if_basic)
{
union REGS regs;
regs.x.bx = the_handle;
regs.h.ah = DRIVER_INFO;
regs.h.al = 0xff;
int86(intno, ®s, ®s);
if(regs.x.cflag)
{
Derr = regs.h.dh;
return -1;
}
if(the_version != NULL) *the_version = regs.x.bx;
if(if_class != NULL) *if_class = regs.h.ch;
if(if_type != NULL) *if_type = regs.x.dx;
if(if_number != NULL) *if_number = regs.h.cl;
if(if_basic != NULL) *if_basic = regs.h.al;
return 0;
}
/*******************************************************************/
/* access_type - begins access to packets of the specified type. */
/* "type" is a pointer to a packet type spec. */
/* "typelen" is the length of this type spec. */
/* "receiver" is a pointer to a function which is */
/* called when a packet is received. */
/* when a packet is received, "receiver" is called */
/* twice by the packet driver. */
/* the first call (ax == 0) is to request a buffer */
/* from the application. if "receiver" */
/* returns a null the packet driver will */
/* throw away the packet. */
/* the second call (ax == 1) indicates that the */
/* packet has been copied to the buffer. */
/*******************************************************************/
int access_type(int intno,
int if_class,
int if_type,
int if_number,
char *the_type,
unsigned typelen,
int far (*receiver)())
{
union REGS regs;
struct SREGS sregs;
segread(&sregs);
regs.h.dl = if_number; /* number */
sregs.ds = FP_SEG(the_type); /* packet type template */
regs.x.si = FP_OFF(the_type);
regs.x.cx = typelen; /* length of type */
sregs.es = FP_SEG(receiver); /* address of receive handler */
regs.x.di = FP_OFF(receiver);
regs.x.bx = if_type; /* type */
regs.h.ah = ACCESS_TYPE; /* access_type() function */
regs.h.al = if_class; /* class */
int86x(intno, ®s, ®s, &sregs);
if(regs.x.cflag)
{
Derr = regs.h.dh;
return -1;
}
else return regs.x.ax;
}
/********************************************************************/
/* release_type - ends access to packets associated with a handle */
/* returned by "access_type()". */
/********************************************************************/
int release_type(int intno,
int handle)
{
union REGS regs;
regs.x.bx = handle;
regs.h.ah = RELEASE_TYPE;
int86(intno, ®s, ®s);
if(regs.x.cflag)
{
Derr = regs.h.dh;
return -1;
}
else return 0;
}
/*******************************************************************/
/* send_pkt - transmits the packet in "buffer". */
/*******************************************************************/
int send_pkt(int intno,
char *buffer,
unsigned length)
{
union REGS regs;
struct SREGS sregs;
segread(&sregs);
sregs.ds = FP_SEG(buffer);
sregs.es = FP_SEG(buffer); /* for buggy univation pkt driver - cdy */
regs.x.si = FP_OFF(buffer);
regs.x.cx = length;
regs.h.ah = SEND_PKT;
int86x(intno, ®s, ®s, &sregs);
if(regs.x.cflag)
{
Derr = regs.h.dh;
return -1;
}
else return 0;
}
/*******************************************************************/
/* terminate - terminates the driver, and if possible allow the */
/* os to reclaim the memory it was using. */
/*******************************************************************/
/* not implemented here. */
/*******************************************************************/
/* get_address - get the local network address of the interface. */
/*******************************************************************/
int get_address (int intno,
int handle,
char *buf,
int len)
{
union REGS regs;
struct SREGS sregs;
segread(&sregs);
sregs.es = FP_SEG(buf);
regs.x.di = FP_OFF(buf);
regs.x.cx = len;
regs.x.bx = handle;
regs.h.ah = GET_ADDRESS;
int86x(intno, ®s, ®s, &sregs);
if(regs.x.cflag)
{
Derr = regs.h.dh;
return -1;
}
return 0;
}
/********************************************************************/
/* reset_interface - resets the interface, aborting any transmits */
/* and reinitializing the receiver. */
/********************************************************************/
/* not implemented here. */
/*******************************************************************/
/* get_parameters - gets certain driver parameters. */
/*******************************************************************/
int get_parameters(int intno)
{
union REGS regs;
struct SREGS sregs;
char far *param;
regs.h.ah = GET_PARAMETERS;
int86x(intno,®s,®s,&sregs);
if(regs.x.cflag)
{
Derr = regs.h.dh;
return -1;
}
param = MK_FP(sregs.es, regs.x.di);
return uchar(param[4]) + 256 * uchar(param[5]);
}
/******************************************************************/
/* support routines */
/******************************************************************/
/******************************************************************/
/* test_for_pd - test for the presence of a packet driver */
/* at an interrupt number. */
/* return 0 if no packet driver. */
/******************************************************************/
int test_for_pd(unsigned int intno)
{
long drvvec;
char sig[8]; /* copy of driver signature "PKT DRVR" */
/* verify that there's really a packet driver there, so we don't
* go off into the ozone (if there's any left).
*/
drvvec = (long)getvect(intno);
movedata(FP_SEG(drvvec), FP_OFF(drvvec)+3,
FP_SEG(sig), FP_OFF(sig), strlen(Pkt_sig));
return !strncmp(sig,Pkt_sig,strlen(Pkt_sig));
}
/* outfile: prog3.out */
/* machine 1 */
ethernet address menu
a. 00.20.af.d8.3c.c0
b. 00.20.af.e4.c9.ff
c. 00.20.af.4e.c9.f4
d. 00.20.af.d8.3c.cc
e. 00.20.af.e4.c9.c5
f. 00.20.af.e4.c9.d3
g. 00.20.af.e4.ca.23
h. 00.20.af.e4.c9.b8
i. 00.20.af.e4.c9.cf
j. 00.20.af.e4.c9.b9
k. 00.20.af.e4.ca.19
l. 00.20.af.e4.c9.83
choose one of the above options: a
send string (locally): hello, computer 2.[cr]
receive string (locally): .2 retupmoc , olleh
-------------------------------------------------------------------------------");
send string (remotely):
receive string (remotely):
/* machine 2 */
ethernet address menu
a. 00.20.af.d8.3c.c0
b. 00.20.af.e4.c9.ff
c. 00.20.af.4e.c9.f4
d. 00.20.af.d8.3c.cc
e. 00.20.af.e4.c9.c5
f. 00.20.af.e4.c9.d3
g. 00.20.af.e4.ca.23
h. 00.20.af.e4.c9.b8
i. 00.20.af.e4.c9.cf
j. 00.20.af.e4.c9.b9
k. 00.20.af.e4.ca.19
l. 00.20.af.e4.c9.83
choose one of the above options:
send string (locally):
receive string (locally):
-------------------------------------------------------------------------------");
send string (remotely): .1 retupmoc ,olleh[cr]
receive string (remotely):hello, computer 1.
BACK TO CS3590 PAGE.