SAMINFO.H

/*++ 

Copyright (c) 1997 Microsoft Corporation

Module Name:

sample\saminfo.h

Abstract:
Public defines and structures exposed by the Sample Routing Protocol DLL

Revision History:


--*/

#ifndef __SAMPLE_INFO_H__
#define __SAMPLE_INFO_H__

#define ANY_SIZE 1

#define SAMPLE_PROTOCOL_NAME "Sample IP Routing Protocol"

//
// The IP Protocol number for this protocol. This is assuming that this
// protocol runs over Raw IP
//

#define SAMPLE_PROTOCOL_ROUTE_ID 100

//
// Assuming this is an IETF protocol with protocol ID 200
//

#define SAMPLE_PROTOCOL_IP_ID \
PROTOCOL_ID(PROTO_TYPE_UNICAST, 0, 0, 200)


//////////////////////////////////////////////////////////////////////////////
// //
// It is highly recommended that implementors provide their own versioning //
// scheme. This sample uses information structures whose first DWORD is //
// the version number. This allows extensibility in the future //
// //
//////////////////////////////////////////////////////////////////////////////

#define SAMPLE_PROTOCOL_VERSION 0x00000001

#define SAMPLE_PROTOCOL_MULTICAST_GROUP1 ((DWORD)0x640000E0) // 224.0.0.100
#define SAMPLE_PROTOCOL_MULTICAST_GROUP2 ((DWORD)0x650000E0) // 224.0.0.101


//////////////////////////////////////////////////////////////////////////////
// //
// The Global Info //
// //
//////////////////////////////////////////////////////////////////////////////

#define PROTO_LOGGING_NONE ((DWORD) 0)
#define PROTO_LOGGING_ERROR ((DWORD) 1)
#define PROTO_LOGGING_WARN ((DWORD) 2)
#define PROTO_LOGGING_INFO ((DWORD) 3)

typedef struct _SAMPLE_PROTOCOL_GLOBAL_INFO
{
DWORD dwVersion;
DWORD dwLogLevel;
}SAMPLE_PROTOCOL_GLOBAL_INFO, *PSAMPLE_PROTOCOL_GLOBAL_INFO;

//////////////////////////////////////////////////////////////////////////////
// //
// An interface an have mutliple addresses. The Sample Routing Protocol //
// allows the admin. to configure parameters for each address. //
// Each Address (or rather <address,mask>) is called a BINDING - for //
// reasons that will be obvious in the code. When there are multiple //
// bindings on an interface, then the IP Addresses are known before //
// hand and do not change while the router is running. If there is //
// only one address, it may or may not be known before the router //
// starts, hence is assumed to be 0.0.0.0. The actual address only //
// becomes available when the IP Router Manager calls the protocol's //
// BindInterface() function. Also such address MAY be dynamic - we //
// say MAY because if the interface has a single static IP Address, //
// it will not change while the router is running. On the other hand, //
// if the interface has a DHCP address (which can only be a SINGLE //
// address) then an ipconfig /release /renew could change the address //
// while the router is running. Since by looking at a single IP address //
// we can not say whether it is dynamic or not, we say that it MAY //
// change. //
// This fact (that address's change) has a bearing on SNMP MIB indices. //
// If the interface has a single IP address, your protocol should be //
// able to handle the information being indexed via the actual address //
// or via 0.0.0.0. This means that the ADDRESS BY ITSELF CAN NOT BE //
// AN INDEX. That is, the interface index MUST be one of the indices //
// //
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// //
// The only information per binding is whether it is enabled or not //
// Hey, this is a SAMPLE, what did you expect - OSPF? //
// //
//////////////////////////////////////////////////////////////////////////////

typedef struct _BINDING_INFO
{
DWORD dwAddress;
DWORD dwMask;
BOOL bEnabled;
}BINDING_INFO, *PBINDING_INFO;

//////////////////////////////////////////////////////////////////////////////
// //
// So the per interface information consists of the information //
// that applies across bindings and information for each binding //
// //
//////////////////////////////////////////////////////////////////////////////

typedef struct _SAMPLE_PROTOCOL_INTERFACE_INFO
{
DWORD dwVersion;
ULONG ulNumBindings;
BINDING_INFO rgbiInfo[ANY_SIZE];
}SAMPLE_PROTOCOL_INTERFACE_INFO, *PSAMPLE_PROTOCOL_INTERFACE_INFO;

#define SIZEOF_PROTO_IF_INFO(X) \
(FIELD_OFFSET(SAMPLE_PROTOCOL_INTERFACE_INFO, rgbiInfo[0]) + \
((X) * sizeof(BINDING_INFO)))


//////////////////////////////////////////////////////////////////////////////
// //
// MIB related information //
// //
// The Sample Routing Protocol only supports queries (Get/GetFirst/GetNext) //
// via the MIB calls. No Sets/Deletes/Creates are supported. The //
// SetInterface/GlobalInfo() calls should be used for that. The reason //
// is to avoid exposing two different interfaces for sets since keeping //
// those in synch is generally difficult. This is a VERY GOOD guideline to //
// follow. EITHER DONT ALLOW ANY SETS THROUGH MIB CALLS OR ONLY ALLOW //
// THOSE VARIABLES TO BE SET THAT ARE NOT SET VIA INTERFACE/GLOBAL INFO //
// CALLS. A case in point being the TTL field exposed via MIB-II. The //
// IP Router Manager allows this field to be set since it is not exposed //
// via the other calls. IN GENERAL USE THE MIB CALLS FOR STATISTICS. //
// This will make coding the admin DLL for the protocol a lot easier. //
// //
//////////////////////////////////////////////////////////////////////////////

#define PROTO_MIB_GLOBAL_ID 0
#define PROTO_MIB_INTF_ID PROTO_MIB_GLOBAL_ID + 1

//////////////////////////////////////////////////////////////////////////////
// //
// The following structure is used to query the MIB. The Oid field is //
// one of the IDs #defined above. The index is stored in a variable //
// sized array. All the indices are DWORDs for this protocol. This is //
// generally a good thing. It wouldn't be the brightest thing to have //
// a string as an index. //
// The number of indices are calculated from the size of the query //
// structure that is passed in to the MibXXX calls. //
// //
//////////////////////////////////////////////////////////////////////////////

typedef struct _PROTO_MIB_QUERY
{
DWORD dwOid;
DWORD rgdwIndex[ANY_SIZE];
}PROTO_MIB_QUERY, *PPROTO_MIB_QUERY;

//////////////////////////////////////////////////////////////////////////////
// //
// Macro to figure out the number of indices given the query size //
// //
//////////////////////////////////////////////////////////////////////////////

#define NUM_INDICES(X) ((X)/sizeof(DWORD) - 1)

//////////////////////////////////////////////////////////////////////////////
// //
// The following structures are the information returned by the protocol in //
// response to a MIB query. Currently they are the same as the //
// Interface/Global structures. However if this were a real protocol, the //
// statistics would go in here and would not be present in the other //
// structures. //
// //
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// //
// The Global info is a scalar and has no index. Unlike SNMP we dont //
// expect a scalar to be indexed by 0 //
// //
//////////////////////////////////////////////////////////////////////////////

typedef struct _PROTO_MIB_GLOBAL
{
DWORD dwLogLevel;
}PROTO_MIB_GLOBAL, *PPROTO_MIB_GLOBAL;

//////////////////////////////////////////////////////////////////////////////
// //
// The Interface info is indexed by the ifIndex //
// //
//////////////////////////////////////////////////////////////////////////////

typedef struct _MIB_BIND
{
DWORD dwAddress;
DWORD dwMask;
BOOL bEnabled;
}MIB_BIND, *PMIB_BIND;

typedef struct _PROTO_MIB_INTF
{
DWORD dwIfIndex;
ULONG ulNumAddress;
MIB_BIND rgmbBindInfo[ANY_SIZE];
}PROTO_MIB_INTF, *PPROTO_MIB_INTF;

#define SIZEOF_MIB_INTF_INFO(X) \
(FIELD_OFFSET(PROTO_MIB_INTF, rgmbBindInfo[0]) + \
((X) * sizeof(MIB_BIND)))


typedef struct _PROTO_MIB_RESPONSE
{
DWORD dwOid;
union
{
PROTO_MIB_GLOBAL mgGlobal;
PROTO_MIB_INTF miIntf;
};
}PROTO_MIB_RESPONSE, *PPROTO_MIB_RESPONSE;

#endif // __SAMPLE_INFO_H__