windows-nt/Source/XPSP1/NT/net/dhcp/server/exim/select.c
2020-09-26 16:20:57 +08:00

309 lines
6.3 KiB
C

/*++
Copyright (c) 2000 Microsoft corporation
Module Name:
select.c
Abstract:
Implements the partial selection of configuration from the
full MM configuration data structures.
--*/
#include <precomp.h>
typedef struct _SELECT_CTXT {
ULONG *Subnets;
ULONG nSubnets;
} SELECT_CTXT, *PSELECT_CTXT;
DWORD
DeleteScopesCallback(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
PSELECT_CTXT SelectCtxt = Ctxt->ExtraCtxt;
ULONG *Subnets, nSubnets, i;
Subnets = SelectCtxt->Subnets;
nSubnets = SelectCtxt->nSubnets;
for( i = 0; i < nSubnets; i ++ ) {
if( Subnets[i] == Ctxt->Scope->Address ) break;
}
if( i == nSubnets ) {
//
// Returning KEY_DELETED will cause the IterateScopes
// routine to delete this scope out.
//
return ERROR_KEY_DELETED;
}
return NO_ERROR;
}
DWORD
OptionCheckForClass(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
PM_CLASSDEF ClassDef = Ctxt->ExtraCtxt;
//
// If the class specified in ExtraCtxt matches the current
// option's user or vendor class, then bummer -- fail
// immediately with error code ERROR_DEVICE_IN_USE to
// indicate that this class is needed and can't be deleted
//
if( Ctxt->UserClass == ClassDef ||
Ctxt->VendorClass == ClassDef ) {
return ERROR_DEVICE_IN_USE;
}
return NO_ERROR;
}
DWORD
OptionCheckForOptDef(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
PMM_ITERATE_CTXT OtherCtxt = Ctxt->ExtraCtxt;
//
// If the current option matches the optdef parameters, then
// we need to save the optdef ..
//
if( Ctxt->VendorClass == OtherCtxt->VendorClass &&
Ctxt->Option->OptId == OtherCtxt->OptDef->OptId ) {
return ERROR_DEVICE_IN_USE;
}
return NO_ERROR;
}
DWORD
ScopeReservationsCheckForClass(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
return IterateReservationOptions(
Ctxt->Server, Ctxt->Res, Ctxt->ExtraCtxt,
OptionCheckForClass );
}
DWORD
ScopeReservationsCheckForOptDef(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
return IterateReservationOptions(
Ctxt->Server, Ctxt->Res, Ctxt->ExtraCtxt,
OptionCheckForOptDef );
}
DWORD
ScopeCheckForClass(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
DWORD Error;
//
// Iterate over each option in the current scope to see if
// any of them use the same class
//
Error = IterateScopeOptions(
Ctxt->Scope, Ctxt->ExtraCtxt, OptionCheckForClass );
if( NO_ERROR != Error ) return Error;
//
// Otherwise iterate for each reservation to see if this is a
// problem.
//
return IterateScopeReservations(
Ctxt->Scope, Ctxt->ExtraCtxt,
ScopeReservationsCheckForClass );
}
DWORD
ScopeCheckForOptDef(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
DWORD Error;
//
// Iterate over each option in the current scope to see if
// any of them use the same class
//
Error = IterateScopeOptions(
Ctxt->Scope, Ctxt->ExtraCtxt, OptionCheckForOptDef );
if( NO_ERROR != Error ) return Error;
//
// Otherwise iterate for each reservation to see if this is a
// problem.
//
return IterateScopeReservations(
Ctxt->Scope, Ctxt->ExtraCtxt,
ScopeReservationsCheckForOptDef );
}
DWORD
DeleteClassesCallback(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
DWORD Error;
//
// Go through each subnet to see if there is any option
// configured to use this class
//
Error = IterateScopes(
Ctxt->Server, Ctxt->ClassDef, ScopeCheckForClass );
//
// If the specified class is in use, then don't
// delete. Otherwise delete.
//
if( ERROR_DEVICE_IN_USE == Error ) return NO_ERROR;
if (NO_ERROR == Error ) return ERROR_KEY_DELETED;
return Error;
}
DWORD
DeleteOptDefsCallback(
IN OUT PMM_ITERATE_CTXT Ctxt
)
{
DWORD Error;
//
// Go through each subnet to see if there is any option
// configured to use this optdef
//
Error = IterateScopes(
Ctxt->Server, Ctxt, ScopeCheckForOptDef );
//
// If the specified class is in use, then don't
// delete. Otherwise delete.
//
if( ERROR_DEVICE_IN_USE == Error ) return NO_ERROR;
if (NO_ERROR == Error ) return ERROR_KEY_DELETED;
return Error;
}
DWORD
SelectConfiguration(
IN OUT PM_SERVER Server,
IN ULONG *Subnets,
IN ULONG nSubnets
)
{
SELECT_CTXT Ctxt = { Subnets, nSubnets };
DWORD Error;
ULONG i;
WCHAR SubnetAddress[30];
//
// No selection needed if nSubnets == 0, as this indicates
// that the whole configuration is to be used
//
Tr("SelectConfiguration entered\n");
if( nSubnets == 0 ) return NO_ERROR;
//
// First go through all scopes and check if all the required
// scopes are present
//
for( i = 0; i < nSubnets ; i ++ ) {
PM_SUBNET Subnet;
Error = MemServerGetUAddressInfo(
Server, Subnets[i], &Subnet, NULL, NULL, NULL );
if( NO_ERROR != Error ) {
Tr("Cant find subnet 0x%lx: %ld\n", Subnets[i], Error );
if( ERROR_FILE_NOT_FOUND == Error ) {
IpAddressToStringW(Subnets[i], (LPWSTR)SubnetAddress);
DhcpEximErrorSubnetNotFound( (LPWSTR)SubnetAddress );
Error = ERROR_CAN_NOT_COMPLETE;
}
return Error;
}
}
//
// Global options are never needed.. so we can delete them.
//
MemOptClassFree( &Server->Options );
//
// Go through all the subnets and delete ones that are
// not selected
//
Error = IterateScopes(
Server, &Ctxt, DeleteScopesCallback );
if( NO_ERROR != Error ) {
Tr("IterateScopes: %ld\n", Error );
return Error;
}
//
// Now check if all the option-defs are needed
//
Error = IterateOptDefs(
Server, NULL, DeleteOptDefsCallback );
if( NO_ERROR != Error ) {
Tr("IterateOptDefs: %ld\n", Error );
return Error;
}
//
// Now check if all the user classes are needed
//
Error = IterateClasses(
Server, NULL, DeleteClassesCallback );
if( NO_ERROR != Error ) {
Tr("IterateClasses: %ld\n", Error );
return Error;
}
return NO_ERROR;
}