Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
ARPSampleShell.c
/* |
File: ARPSampleShell.c |
Contains: Sample that shows how to talk to the ARP module. |
Written by: Quinn "The Eskimo!" |
Copyright: Copyright © 1997-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
7/21/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
/////////////////////////////////////////////////////////////////// |
// Lots of standard OT constructs. |
#include <OpenTptClient.h> |
#include <OpenTptInternet.h> |
#include <Memory.h> |
/////////////////////////////////////////////////////////////////// |
// This sample makes heavy use of C's standard I/O package. |
#include <stdio.h> |
/////////////////////////////////////////////////////////////////// |
// Standard C string operations. |
#include <string.h> |
/////////////////////////////////////////////////////////////////// |
// Constants and types for ARP module messages. |
#include "OTARPModule.h" |
/////////////////////////////////////////////////////////////////// |
// Prototypes for our high-level interface to ARP. |
#include "ARPerations.h" |
/////////////////////////////////////////////////////////////////// |
// Define a structure for holding a standard hardware address, |
// ie a 6 byte Ethernet address. |
struct HardwareAddress { |
UInt8 fHardwareAddress[6]; |
}; |
typedef struct HardwareAddress HardwareAddress; |
/////////////////////////////////////////////////////////////////// |
// Define constants for all the default address and such that we |
// assume if you enter a blank field. |
static char kDefaultInterfaceName[] = "pci1011,140"; |
static HardwareAddress kDefaultHardwareAddress = { 0x00, 0x05, 0x02, 0xBC, 0xC8, 0x4F }; |
static InetHost kDefaultIPAddress = ( (17L << 24) || (203L << 16) || (21L << 8) || 98); |
static char kDefaultInterfaceConfig[] = "enet"; |
/////////////////////////////////////////////////////////////////// |
// Routines for reading and writing various address types. |
static void GetHardwareAddress(HardwareAddress *hwAddr) |
// Prompt the user for a hardware address. |
{ |
unsigned int hw0, hw1, hw2, hw3, hw4, hw5; |
int result; |
char tmpStr[256]; |
printf("Enter a hardware address:\n"); |
tmpStr[0] = 0; |
gets(tmpStr); |
printf("Ò%sÓ\n", tmpStr); |
result = sscanf(tmpStr, "%x:%x:%x:%x:%x:%x", &hw0, &hw1, &hw2, &hw3, &hw4, &hw5); |
if (result != 6) { |
printf("Wrong answer. Using default hardware address.\n"); |
*hwAddr = kDefaultHardwareAddress; |
} else { |
hwAddr->fHardwareAddress[0] = hw0; |
hwAddr->fHardwareAddress[1] = hw1; |
hwAddr->fHardwareAddress[2] = hw2; |
hwAddr->fHardwareAddress[3] = hw3; |
hwAddr->fHardwareAddress[4] = hw4; |
hwAddr->fHardwareAddress[5] = hw5; |
} |
} |
static void HardwareAddressToString(HardwareAddress hwAddr, char *outputString) |
// Convert a hardware address to a string suitable for printing. |
{ |
sprintf(outputString, "%02x:%02x:%02x:%02x:%02x:%02x", |
hwAddr.fHardwareAddress[0], |
hwAddr.fHardwareAddress[1], |
hwAddr.fHardwareAddress[2], |
hwAddr.fHardwareAddress[3], |
hwAddr.fHardwareAddress[4], |
hwAddr.fHardwareAddress[5] |
); |
} |
static void GetInterfaceName(char *intfName) |
// Prompt the user for an interface name. |
{ |
printf("Enter an ARP interface name (press return for Ò%sÓ):\n", kDefaultInterfaceName); |
intfName[0] = 0; |
gets(intfName); |
if (intfName[0] == 0) { |
strcpy(intfName, kDefaultInterfaceName); |
} |
} |
static void GetIPAddress(InetHost *ipAddr) |
// Prompt the user for an IP address. |
{ |
char tmpStr[256]; |
unsigned int ip0, ip1, ip2, ip3; |
int result; |
printf("Enter an IP address:\n"); |
tmpStr[0] = 0; |
gets(tmpStr); |
result = sscanf(tmpStr, "%d.%d.%d.%d", &ip0, &ip1, &ip2, &ip3); |
if (result != 4) { |
printf("Wrong answer. Using default IP address.\n"); |
*ipAddr = kDefaultIPAddress; |
} else { |
*ipAddr = (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3; |
} |
} |
static void IPAddressToString(InetHost ipAddr, char *outputString) |
// Convert an IP address to a string suitable for printing. |
{ |
sprintf(outputString, "%d.%d.%d.%d", |
(ipAddr >> 24) & 0x0ff, |
(ipAddr >> 16) & 0x0ff, |
(ipAddr >> 8) & 0x0ff, |
(ipAddr >> 0) & 0x0ff |
); |
} |
static void GetFlag(char *flagName, UInt32 flagValue, UInt32 *flags) |
// Prompt the user for a flag. The flagName is the user-visible |
// name of the flag. If the user types anything other than |
// return or "n", flagVlaue is ORed into the flags variable. |
{ |
char tmpStr[256]; |
printf("%s? (y/n)\n", flagName); |
gets(tmpStr); |
if ( tmpStr[0] != 0 && tmpStr[0] != 'n' && tmpStr[0] != 'N') { |
(*flags) |= flagValue; |
} |
} |
static void PrintFlag(char *flagName, UInt32 flagMask, UInt32 flags) |
// Print a flag. |
{ |
if ( (flags & flagMask) != 0 ) { |
printf("%s ", flagName); |
} |
} |
/////////////////////////////////////////////////////////////////// |
static OSStatus DoARPGetCacheReport(void) |
// Call through to the equivalent ARPerations routine |
// and then print the results. |
{ |
OSStatus err; |
Handle cacheReportHandle; |
char zero; |
printf("DoARPGetCacheReport\n"); |
cacheReportHandle = NewHandle(0); |
err = MemError(); |
if (err == noErr) { |
err = ARPGetCacheReport(cacheReportHandle); |
if (err == noErr) { |
zero = 0; |
err = PtrAndHand(&zero, cacheReportHandle, sizeof(zero)); |
if (err == noErr) { |
HLock(cacheReportHandle); |
printf("%s\n\n", *cacheReportHandle); |
} |
} |
DisposeHandle(cacheReportHandle); |
} |
printf("\n"); |
return (err); |
} |
/////////////////////////////////////////////////////////////////// |
static OSStatus DoARPAddEntry(void) |
// Prompt user for input and then call straight through |
// to the equivalent ARPerations routine. |
{ |
OSStatus err; |
char interfaceName[256]; |
InetHost ipAddr; |
InetHost ipMask = 0xFFFFFFFF; |
HardwareAddress hwAddr; |
char ipAddrString[256]; |
char hwAddrString[256]; |
UInt32 flags; |
printf("DoARPAddEntry\n"); |
GetInterfaceName(interfaceName); |
GetIPAddress(&ipAddr); |
IPAddressToString(ipAddr, ipAddrString); |
GetHardwareAddress(&hwAddr); |
HardwareAddressToString(hwAddr, hwAddrString); |
flags = 0; |
GetFlag("PERM ", ACE_F_PERMANENT, &flags); |
GetFlag("PUBLISH", ACE_F_PUBLISH, &flags); |
GetFlag("MAPPING", ACE_F_MAPPING, &flags); |
printf("Adding ARP cache entry for %s -> %s on Ò%sÓ.\n", ipAddrString, hwAddrString, interfaceName); |
err = ARPAddEntry(interfaceName, IP_ARP_PROTO_TYPE, flags, |
&ipAddr, sizeof(InetHost), &ipMask, &hwAddr, sizeof(hwAddr)); |
return (err); |
} |
/////////////////////////////////////////////////////////////////// |
static OSStatus DoARPDeleteEntry(void) |
// Prompt user for input and then call straight through |
// to the equivalent ARPerations routine. |
{ |
OSStatus err; |
InetHost ipAddr; |
char interfaceName[256]; |
char ipAddrString[256]; |
printf("DoARPDeleteEntry\n"); |
GetInterfaceName(interfaceName); |
GetIPAddress(&ipAddr); |
IPAddressToString(ipAddr, ipAddrString); |
printf("Deleting ARP cache entry for %s on Ò%sÓ.\n", ipAddrString, interfaceName); |
err = ARPDeleteEntry(interfaceName, IP_ARP_PROTO_TYPE, &ipAddr, sizeof(InetHost)); |
return (err); |
} |
/////////////////////////////////////////////////////////////////// |
static OSStatus DoARPCacheQuery(void) |
// Prompt user for input, call through to the equivalent |
// ARPerations routine, and then print the results. |
{ |
OSStatus err; |
char interfaceName[256]; |
InetHost ipAddr; |
HardwareAddress hwAddr; |
char ipAddrString[256]; |
char hwAddrString[256]; |
UInt32 flags; |
printf("DoARPCacheQuery\n"); |
GetInterfaceName(interfaceName); |
GetIPAddress(&ipAddr); |
IPAddressToString(ipAddr, ipAddrString); |
printf("Lookup ARP cache entry for %s on Ò%sÓ.\n", ipAddrString, interfaceName); |
err = ARPCacheQuery(interfaceName, |
IP_ARP_PROTO_TYPE, |
&ipAddr, sizeof(InetHost), |
&hwAddr, sizeof(hwAddr), &flags); |
if (err == noErr) { |
HardwareAddressToString(hwAddr, hwAddrString); |
printf("Hardware address is %s.\n", hwAddrString); |
printf("Flags are "); |
PrintFlag("PERM", ACE_F_PERMANENT, flags); |
PrintFlag("PUBLISH", ACE_F_PUBLISH, flags); |
PrintFlag("DYING", ACE_F_DYING, flags); |
PrintFlag("RESOLVED", ACE_F_RESOLVED, flags); |
PrintFlag("MAPPING", ACE_F_MAPPING, flags); |
printf("\n"); |
} |
return (err); |
} |
/////////////////////////////////////////////////////////////////// |
// This sample uses a big global array (gInterfacesWeBroughtUp) to store |
// the list of interfaces that we have brought up. The top of this |
// array is defined by gMaxInterfaceIndex. The array stores |
// the configuration string used to create the interface (so that |
// we can display it to the user) and the interfaceCookie returned |
// by ARPInterfaceUp (so we can pass it back to ARPInterfaceDown |
// to tear down the interface). |
enum { |
kNumberOfOurARPInterfaces = 10 // Obviously an arbitrary limit. |
}; |
struct InterfaceInfo { |
UInt32 cookie; |
char configString[256]; |
}; |
typedef struct InterfaceInfo InterfaceInfo; |
static InterfaceInfo gInterfacesWeBroughtUp[kNumberOfOurARPInterfaces]; |
static SInt32 gMaxInterfaceIndex = -1; |
static OSStatus DoARPPrintOurInterfaces(void) |
// Print the list of ARP interfaces we have brought up. |
{ |
SInt32 interfaceIndex; |
printf("DoARPPrintOurInterfaces\n"); |
printf("Interfaces we brought up:\n"); |
for (interfaceIndex = 0; interfaceIndex <= gMaxInterfaceIndex; interfaceIndex++) { |
printf("%2d -- %s\n", |
interfaceIndex, |
gInterfacesWeBroughtUp[interfaceIndex].configString |
); |
} |
printf("\n"); |
return (noErr); |
} |
static OSStatus DoARPInterfaceUp(void) |
// Prompt user for input and then call through to ARPInterfaceUp |
// to bring up the interface. If this succeeds, record the |
// interface in gInterfacesWeBroughtUp so we can tear it down |
// again. |
{ |
OSStatus err; |
printf("DoARPInterfaceUp\n"); |
err = noErr; |
if ( gMaxInterfaceIndex == (kNumberOfOurARPInterfaces - 1) ) { |
err = -3; |
} |
if (err == noErr) { |
printf("Enter the configuration string of the interface you want to bring up:\n"); |
gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString[0] = 0; |
gets(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString); |
if ( gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString[0] == 0 ) { |
OTStrCopy(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString, kDefaultInterfaceConfig); |
} |
} |
if (err == noErr) { |
err = ARPInterfaceUp(gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].configString, |
&gInterfacesWeBroughtUp[gMaxInterfaceIndex + 1].cookie); |
} |
if (err == noErr) { |
gMaxInterfaceIndex += 1; |
} |
return (err); |
} |
static OSStatus DoARPInterfaceDown(void) |
// Prompt user for the numeric index of the interface they |
// want to tear down, and then call through to ARPInterfaceDown |
// to tear it down. Afterwards, delete the torn down element from |
// the gInterfacesWeBroughtUp array |
{ |
OSStatus err; |
SInt32 interfaceIndex; |
char tmpStr[256]; |
printf("DoARPInterfaceDown\n"); |
(void) DoARPPrintOurInterfaces(); |
printf("Enter an interface to take down:\n"); |
tmpStr[0] = 0; |
gets(tmpStr); |
err = noErr; |
if ( sscanf(tmpStr, "%ld", &interfaceIndex) != 1 ) { |
err = -1; |
} |
if (err == noErr) { |
if ( (interfaceIndex < 0) || (interfaceIndex > gMaxInterfaceIndex) ) { |
err = -2; |
} |
} |
if (err == noErr) { |
err = ARPInterfaceDown(gInterfacesWeBroughtUp[interfaceIndex].cookie); |
} |
if (err == noErr) { |
gInterfacesWeBroughtUp[interfaceIndex] = gInterfacesWeBroughtUp[gMaxInterfaceIndex]; |
gMaxInterfaceIndex -= 1; |
} |
return (err); |
} |
/////////////////////////////////////////////////////////////////// |
static OSStatus DoPrintCommandHelp(void) |
// Print the current list of commands. |
{ |
printf("DoPrintCommandHelp\n"); |
printf("?) Prints this help.\n"); |
printf("\n"); |
printf("p) Print contents of ARP cache.\n"); |
printf("a) Add an ARP cache entry.\n"); |
printf("k) Delete an ARP cache entry.\n"); |
printf("l) Lookup an ARP cache entry.\n"); |
printf("\n"); |
printf("i) See the ARP interfaces we have brought up.\n"); |
printf("u) Bring up a new ARP interface.\n"); |
printf("d) Tear down an ARP interface.\n"); |
printf("\n"); |
printf("q) Quit.\n"); |
return (noErr); |
} |
/////////////////////////////////////////////////////////////////// |
void main(void) |
{ |
OSStatus err; |
char commandStr[256]; |
Boolean quitNow; |
printf("ARPSample -- A poor man's ARPing tool.\n"); |
err = InitOpenTransport(); |
if (err == noErr) { |
quitNow = false; |
(void) DoPrintCommandHelp(); |
// Welcome to the command loop. Get a string from the user |
// and use the first letter to dispatch to the relevant |
// subroutine. |
do { |
printf("Enter a letter corresponding to a command.\n"); |
err = noErr; |
gets(commandStr); |
switch (commandStr[0]) { |
case '?': |
err = DoPrintCommandHelp(); |
break; |
case 'p': |
err = DoARPGetCacheReport(); |
break; |
case 'a': |
err = DoARPAddEntry(); |
break; |
case 'k': |
err = DoARPDeleteEntry(); |
break; |
case 'l': |
err = DoARPCacheQuery(); |
break; |
case 'i': |
err = DoARPPrintOurInterfaces(); |
break; |
case 'u': |
err = DoARPInterfaceUp(); |
break; |
case 'd': |
err = DoARPInterfaceDown(); |
break; |
case 'q': |
quitNow = true; |
break; |
case '\n': |
break; |
default: |
printf("Huh? Ò%sÓ\n", commandStr); |
break; |
} |
if (err != noErr) { |
printf("Error %ld.\n", err); |
} |
} while ( ! quitNow ); |
CloseOpenTransport(); |
} |
if (err == noErr) { |
printf("Success.\n"); |
} else { |
printf("Failed with error %d.\n", err); |
} |
printf("Done. Press command-Q to Quit.\n"); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22