/* Version X-8 */ /************************************************************************ ** * ** Copyright © 1996 Digital Equipment Corporation. * ** All rights reserved. * ** * ** Redistribution and use in source and binary forms are permitted * ** provided that the above copyright notice and this paragraph are * ** duplicated in all such forms and that any documentation, * ** advertising materials, and other materials related to such * ** distribution and use acknowledge that the software was developed * ** by Digital Equipment Corporation. The name of the * ** Corporation may not be used to endorse or promote products derived * ** from this software without specific prior written permission. * ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * ** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * ** WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * ** * ** * ************************************************************************* ** * ** Important Note: * ** * ** This coding example uses privileged OpenVMS interfaces. * ** OpenVMS does not guarantee that these interfaces will * ** be supported indefinitely, and may change these interfaces * ** without prior notice. * ** * ************************************************************************* **++ ** FACILITY: ** ** ip_vcm.c ** ** ABSTRACT: ** ** This module implements a basic VCM for testing PPP. ** ** AUTHORS: ** ** Patrick Crilly, Networks Engineering (Australia). ** ** CREATION DATE: ** ** 25-March-1996 ** ** Modified by: ** ** X-8 ACG0710 Andy Goldstein, 30-Nov-2007 15:56 ** Remove SDL workaround for embedded VCIBDEF ** ** 12-March-1997 Joe P. Tavares ** Add fork_lock and fork_unlock to startProtocol. ** ** 17-December-1996 Barry W. Kierstein ** Replaced the standard Digital copyright with ** one compatible with the CMU copyright. ** ** ** 1-October-1996 Forrest A. Kenney ** Remove 4 character terminal name restriction. ** ** 1-August-1996 Barry W. Kierstein ** Added "Important Note" disclaimer. ** ** 24-July-1996 Barry W. Kierstein ** Corrected copyright notice. ** ** 25-March-1996 Original version. ** **-- */ #define MAX_TERMINAL_NAME 20 /* ** Include files */ #include "ssdef.h" /* Include SS$_xxx defintions */ #include "string.h" /* Include string defintions */ #include "vcrpdef.h" /* Include vcrp defintions */ #include "vcibdef.h" /* Include vcib defintions */ #include "ppp_vci_if.h" /* Include PPP VCI defintions */ #include "ppp_lib.h" /* Include PPP library prototype */ #include "vms_drivers.h" /* VMS device driver macros */ /* ** Global variables */ VCIRTNS *VCIFns; /* Pointer to PPP VCI's create/delete port routines */ VCIBPPPDEF IPVcib; /* VCIB for connecting to PPP VCM */ struct vcrpdef mgmtReq; /* VCRP for issuing PortMgmt_Initiate requests */ int IPPktsSent; /* Count of packets transmitted */ /* external functions */ extern int VCICreate(); extern int VCIDelete(); extern void VCICall(); /* forward declare routines */ int startProtocol( char *ttDevName ); void stopProtocol( void ); /* Transmit Complete */ #pragma linkage VCITxComplLnkg = (parameters(r4,r3), preserved(r2,r4,r5), nopreserve(r0,r1)) #pragma use_linkage VCITxComplLnkg (VCITxCompl) void VCITxCompl( VCIBPPPDEF *vcib, struct vcrpdef *request ); /* PortMgmt Complete */ #pragma linkage VCIMgmtComplLnkg = (parameters(r4,r3), preserved(r2,r4,r5), nopreserve(r0,r1)) #pragma use_linkage VCIMgmtComplLnkg (VCIMgmtCompl) void VCIMgmtCompl( VCIBPPPDEF *vcib, struct vcrpdef *request ); /* Receive */ #pragma linkage VCIRxLnkg = (parameters(r4,r3), preserved(r2,r4,r5), nopreserve(r0,r1)) #pragma use_linkage VCIRxLnkg (VCIRxCompl) void VCIRxCompl( VCIBPPPDEF *vcib, struct vcrpdef *request ); /* Events */ #pragma linkage VCIReportLnkg = (parameters(r4,r1, r2), preserved(r5), nopreserve(r0,r1)) #pragma use_linkage VCIReportLnkg (VCIRptEvent) void VCIRptEvent( VCIBPPPDEF *vcib, int event, int reason ); /* **++ ** FUNCTION NAME: ** ** startProtocol ** ** FUNCTIONAL DESCRIPTION: ** ** This routine is called to start a protocol (in this case IP) ** running over PPP. It just creates a VCI port to PPP and ** then issues a PortMgmt_Initiate ENABLE_PORT request. ** ** Because of the way his routine is coded the name of the device ** can't be more than 5 characters. Hey - this is sample code ** afterall, I've left the good bits for you. ** ** FORMAL PARAMETERS: ** ** ttDevName Name of PPP device to start the protocol on ** ** IMPLICIT INPUTS: ** ** None. ** ** IMPLICIT OUTPUTS: ** ** None. ** ** function value or completion codes ** ** status returned by PPP VCI CreatePort routine ** ** SIDE EFFECTS: ** ** None. ** **-- */ int startProtocol( char *ttDevName ) { int saved_ipl; int status; struct PPPItemList { int length; void *addr; unsigned short size; unsigned char type; unsigned char subType; unsigned short protoLen; unsigned short protoItem; unsigned short proto; unsigned short nameLen; unsigned short nameItem; unsigned char name[MAX_TERMINAL_NAME]; } PPPItemList; /* Item list for Enable Port request */ /* initialise count of packets sent */ IPPktsSent = 0; /* get pointer to create/delete routines */ VCIFns = (VCIRTNS *)PPPD$LIBRTNS( PPP_VCI_RTNS ); if ( !VCIFns ) { return ( SS$_ABORT ); } /* Set up the VCIB for connecting to PPP */ IPVcib.vcib$r_vcibdef.vcib$a_portmgmt_complete = (void *)VCIMgmtCompl; IPVcib.vcib$r_vcibdef.vcib$a_transmit_complete = (void *)VCITxCompl; IPVcib.vcib$r_vcibdef.vcib$a_receive_complete = (void *)VCIRxCompl; IPVcib.vcib$r_vcibdef.vcib$a_report_event = (void *)VCIRptEvent; fork_lock(SPL$C_IOLOCK8, &saved_ipl); /* create a port to PPP */ status = VCICreate( VCIFns->createport, &IPVcib ); /* enable port */ if ( status == SS$_NORMAL ) { /* Set up the item list for the Enable Port request */ PPPItemList.protoLen = 6; PPPItemList.protoItem = PPPD$K_PROTOCOL; PPPItemList.proto = 0x0021; /* IP */ PPPItemList.nameLen = strlen(ttDevName) + 4; PPPItemList.nameItem = PPPD$K_NAME; strncpy( (char *)PPPItemList.name, ttDevName, strlen(ttDevName) ); PPPItemList.length = PPPItemList.nameLen + PPPItemList.protoLen; PPPItemList.addr = &PPPItemList.protoLen; PPPItemList.size = sizeof(PPPItemList); /* Set up VCRP for Enable Port request */ mgmtReq.vcrp$a_input_list = (void *)&PPPItemList; mgmtReq.vcrp$l_function = VCRP$K_FC_ENABLE_PORT; /* Call Enable Port */ VCICall( IPVcib.vcib$r_vcibdef.vcib$a_portmgmt_initiate, &mgmtReq, &IPVcib ); } fork_unlock(SPL$C_IOLOCK8, saved_ipl, SMP_RESTORE) return (status); } /* **++ ** FUNCTION NAME: ** ** stopProtocol ** ** FUNCTIONAL DESCRIPTION: ** ** This routine is called to stop a protocol running over PPP. ** It just issues a PortMgmt_Initiate DISABLE_PORT request. ** ** FORMAL PARAMETERS: ** ** None. ** ** IMPLICIT INPUTS: ** ** None. ** ** IMPLICIT OUTPUTS: ** ** None. ** ** function value or completion codes ** ** None. ** ** SIDE EFFECTS: ** ** None. ** **-- */ void stopProtocol( ) { /* Set up VCRP for Disable request */ mgmtReq.vcrp$a_input_list = 0; mgmtReq.vcrp$l_function = VCRP$K_FC_DISABLE_PORT; /* Call disable routine */ VCICall( IPVcib.vcib$r_vcibdef.vcib$a_portmgmt_initiate, &mgmtReq, &IPVcib ); } /* **++ ** FUNCTION NAME: ** ** VCIMgmtCompl ** ** FUNCTIONAL DESCRIPTION: ** ** This function processes the asychronous completion of a ** PortMgmt_Initiate request. ** ** FORMAL PARAMETERS: ** ** vcib Pointer to the vcib the request completed on ** request Pointer to the vcrp containing the request transmit ** ** IMPLICIT INPUTS: ** ** None. ** ** IMPLICIT OUTPUTS: ** ** None. ** ** function value or completion codes ** ** None. ** ** SIDE EFFECTS: ** ** None. ** **-- */ void VCIMgmtCompl( VCIBPPPDEF *vcib, struct vcrpdef *request ) { if ( mgmtReq.vcrp$l_function == VCRP$K_FC_DISABLE_PORT ) { /* ** Really should check status of disable here. Disable should ** only fail though if called more than once without a completion ** being received so I going to be slack, this is only an example. */ /* close PPP port */ VCIDelete( VCIFns->deleteport, &IPVcib ); } else { /* an enable request */ if ( mgmtReq.vcrp$l_request_status != SS$_NORMAL ) { stopProtocol(); } } return; } /* **++ ** FUNCTION NAME: ** ** VCIRxCompl ** ** FUNCTIONAL DESCRIPTION: ** ** This function processes a received packet. ** For this example when send the packet straight back. ** After sending 6 packets we stop the protocol. ** ** FORMAL PARAMETERS: ** ** vcib Pointer to the vcib the packet on ** request Pointer to the vcrp containing the received packet ** ** IMPLICIT INPUTS: ** ** None. ** ** IMPLICIT OUTPUTS: ** ** None. ** ** function value or completion codes ** ** None. ** ** SIDE EFFECTS: ** ** None. ** **-- */ void VCIRxCompl( VCIBPPPDEF *vcib, struct vcrpdef *request ) { /* Turn the receive into a transmit packet */ request->vcrp$l_function = VCRP$K_FC_TRANSMIT; /* Call transmit routine */ VCICall( IPVcib.vcib$r_vcibdef.vcib$a_transmit_initiate, request, &IPVcib ); IPPktsSent++; /* After 6 packet sent sent stop protocol */ if ( IPPktsSent > 5 ) { stopProtocol(); } return; } /* **++ ** FUNCTION NAME: ** ** VCITxCompl ** ** FUNCTIONAL DESCRIPTION: ** ** This function processes the asychronous completion of a ** Transmit_Initiate request. ** ** FORMAL PARAMETERS: ** ** vcib Pointer to the vcib the transmit completed on ** request Pointer to the vcrp containing the completed transmit ** ** IMPLICIT INPUTS: ** ** None. ** ** IMPLICIT OUTPUTS: ** ** None. ** ** function value or completion codes ** ** None. ** ** SIDE EFFECTS: ** ** None. ** **-- */ void VCITxCompl( VCIBPPPDEF *vcib, struct vcrpdef *request ) { /* If the transmit failed for any reason stop the protocol */ if ( request->vcrp$l_request_status != SS$_NORMAL ) { stopProtocol(); } return; } /* **++ ** FUNCTION NAME: ** ** VCIRptEvent ** ** FUNCTIONAL DESCRIPTION: ** ** This function processes the asychronous notification ** of an event ** ** FORMAL PARAMETERS: ** ** vcib Pointer to the vcib the event occurred on ** event The event that occurred ** reason Reason that caused the event (to be honest I don't care - you might) ** ** IMPLICIT INPUTS: ** ** None. ** ** IMPLICIT OUTPUTS: ** ** None. ** ** function value or completion codes ** ** None. ** ** SIDE EFFECTS: ** ** None. ** **-- */ void VCIRptEvent( VCIBPPPDEF *vcib, int event, int reason ) { switch (event) { case PPPD$K_PORT_FAILED: /* stop the protocol running */ stopProtocol(); break; case PPPD$K_PORT_USABLE: /* can start transmitting IP packets */ break; case PPPD$K_PORT_UNUSABLE: /* must stop transmitting IP packets */ break; } return; }