//================================================================================ // Copyright (C) 1997 Microsoft Corporation // Author: RameshV // Description: Download and Upload related code. //================================================================================ //================================================================================ // includes //================================================================================ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //================================================================================ // utilities //================================================================================ //DOC DhcpDsServerGetLastUpdateTime gets the last update time for this server in the DS DWORD DhcpDsServerGetLastUpdateTime( // get last update time for server IN LPSTORE_HANDLE hServer, // server to get last update time of IN OUT LPFILETIME Time // set this struct appropriately ) { HRESULT Err; DWORD nAttributes; LPWSTR TimeAttrName; // attribute name for time.. PADS_ATTR_INFO Attributes; SYSTEMTIME SysTime; TimeAttrName = DHCP_ATTRIB_WHEN_CHANGED; Attributes = NULL; nAttributes = 0; Err = ADSIGetObjectAttributes // now read the last changed time attr ( hServer->ADSIHandle, &TimeAttrName, 1, // only 1 attribute in above array &Attributes, &nAttributes ); if( FAILED(Err) || 0 == nAttributes || 0 == Attributes->dwNumValues ) { if( Attributes ) { FreeADsMem(Attributes); return ERROR_GEN_FAILURE; // blanket error? maybe better err msg.. } return ConvertHresult(Err); } if( Attributes->pADsValues[0].dwType != ADSTYPE_UTC_TIME ) { FreeADsMem(Attributes); return ERROR_GEN_FAILURE; // unexpected data format } SysTime = Attributes->pADsValues[0].UTCTime; // copy time structs FreeADsMem(Attributes); Err = SystemTimeToFileTime(&SysTime, Time); // try to convert to filetime struct if( FAILED( Err ) ) return GetLastError(); // something went wrong? return ERROR_SUCCESS; } BOOL _inline AddressFoundInHostent( IN DHCP_IP_ADDRESS AddrToSearch, // Host-Order addr IN HOSTENT *ServerEntry // entry to search for.. ) { ULONG nAddresses, ThisAddress; if( NULL == ServerEntry ) return FALSE; // no address to search in nAddresses = 0; // have a host entry to compare for addresses while( ServerEntry->h_addr_list[nAddresses] ) { ThisAddress = ntohl(*(DHCP_IP_ADDRESS*)ServerEntry->h_addr_list[nAddresses++] ); if( ThisAddress == AddrToSearch ) { return TRUE; // yeah address matched. } } return FALSE; } //================================================================================ // exports //================================================================================ //BeginExport(function) //DOC DhcpDsGetLastUpdateTime gets the last update time for the server //DOC specified by name. If the server does not exist, or if server object doesnt //DOC exist, then an error is returned. If the time value //DOC does not exist on the server object, again, an error is returned. DWORD DhcpDsGetLastUpdateTime( // last update time for server IN LPWSTR ServerName, // this is server of interest IN OUT LPFILETIME Time // fill in this w./ the time ) //EndExport(function) { DWORD Err,i, LocType ; LPDHCPDS_SERVERS Servers; extern STORE_HANDLE hDhcpC, hDhcpRoot; // From rpcstubs.c LPWSTR Location, LocStr; BOOL Found; STORE_HANDLE hServer; HOSTENT *ServerEntry; if( NULL == ServerName ) return ERROR_INVALID_PARAMETER; do { // name to IP lookup CHAR TmpBuf[300]; wcstombs(TmpBuf, ServerName, sizeof(TmpBuf)-1); TmpBuf[sizeof(TmpBuf)-1] = '\0'; ServerEntry = gethostbyname(TmpBuf); } while(0); Servers = NULL; Err = DhcpDsEnumServers // first get a list of servers ( /* hDhcpC */ &hDhcpC, // frm rpcstubs.c, opened in DhcpDsInitDS /* hDhcpRoot */ &hDhcpRoot, // ditto /* Reserved */ DDS_RESERVED_DWORD, /* ServersInfo */ &Servers ); if( ERROR_SUCCESS != Err ) { Time->dwLowDateTime = Time->dwHighDateTime = 0; return Err; // error.. return w/ no time } Found = FALSE; LocStr = Location = NULL; // initialize.. for( i = 0; i < Servers->NumElements ; i ++ ) { if( 0 != _wcsicmp(ServerName, Servers->Servers[i].ServerName) && !AddressFoundInHostent(Servers->Servers[i].ServerAddress, ServerEntry) ) { continue; // ughm.. not the same server.. } else { // ok got the server Location = Servers->Servers[i].DsLocation; LocType = Servers->Servers[i].DsLocType; Found = TRUE; if( NULL != Location ) break; } } if( ! Found ) { // could not find server in list..? MemFree(Servers); return ERROR_FILE_NOT_FOUND; } if( NULL == Location ) { // could not find server location? MemFree(Servers); // dont need this anymore Servers = NULL; Location = MakeColumnName(ServerName); // just presume it is under hDhcpC container LocType = StoreGetChildType; // child type if( NULL == Location ) return ERROR_NOT_ENOUGH_MEMORY; } Err = StoreGetHandle // now try to open the server object ( /* hStore */ &hDhcpC, /* Reserved */ DDS_RESERVED_DWORD, /* StoreGetType */ LocType, /* Path */ Location, /* hStoreOut */ &hServer ); if( Servers ) { // Location points into this MemFree(Servers); // freeing this also free Location } else { // Location is allocated memory MemFree(Location); } if( ERROR_SUCCESS != Err ) return Err; // some DS trouble? Err = DhcpDsServerGetLastUpdateTime(&hServer, Time); (void)StoreCleanupHandle(&hServer, 0); // assume this wont fail. return Err; } //DOC ServerUploadClasses does rpc calls to server and copies stuff over to DS. DWORD ServerUploadClasses( // upload classes info to DS IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container to store at IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerAddress // server ip address ) { DWORD Err, Resume, PrefMax, i, nRead, nTotal; LPDHCP_CLASS_INFO_ARRAY ClassesInfo; Resume = 0; PrefMax = 0xFFFFFFFF; nRead = nTotal = 0; ClassesInfo = NULL; Err = DhcpEnumClasses(ServerAddress, 0, &Resume, PrefMax, &ClassesInfo, &nRead, &nTotal); if( ERROR_NO_MORE_ITEMS == Err ) return ERROR_SUCCESS; if( ERROR_SUCCESS != Err ) return Err; // could not enumerate classes. for( i = 0; i < ClassesInfo->NumElements; i ++ ) { Err = DhcpCreateClassDS(ServerAddress, 0, &ClassesInfo->Classes[i]); if( ERROR_SUCCESS != Err ) break; #if 0 Err = ServerUploadOptDefsForClass( hDhcpC, hServer, ServerAddress, ClassesInfo->Classes[i].ClassName ); if( ERROR_SUCCESS != Err ) break; #endif } if( ClassesInfo ) MemFree(ClassesInfo); return Err; } //DOC ServerUploadOptdefs does rpc calls to server and copies stuff over to DS DWORD ServerUploadOptdefs( // upload opt defs info to DS IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container to store at IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerAddress // server ip address ) { DWORD Err, i; LPDHCP_ALL_OPTIONS Options; Options = NULL; Err = DhcpGetAllOptions(ServerAddress,0, &Options); if( ERROR_NO_MORE_ITEMS == Err ) return ERROR_SUCCESS; if( ERROR_SUCCESS != Err ) return Err; if( Options->NonVendorOptions ) { for( i = 0; i < Options->NonVendorOptions->NumElements; i ++ ) { Err = DhcpCreateOptionV5DS( ServerAddress, 0, Options->NonVendorOptions->Options[i].OptionID, NULL /* no class */, NULL /* no vendor */, &Options->NonVendorOptions->Options[i] ); if( ERROR_SUCCESS != Err ) break; } } if( ERROR_SUCCESS != Err ) { MemFree(Options); return Err; } for( i = 0; i < Options->NumVendorOptions; i ++ ) { Err = DhcpCreateOptionV5DS( ServerAddress, DHCP_FLAGS_OPTION_IS_VENDOR, Options->VendorOptions[i].Option.OptionID, Options->VendorOptions[i].ClassName, Options->VendorOptions[i].VendorName, &Options->VendorOptions[i].Option ); if( ERROR_SUCCESS != Err ) break; } if( ERROR_SUCCESS != Err ) { MemFree(Options); return Err; } if( Options ) MemFree(Options); return Err; } //DOC UploadOptiosn does rpc calls to server and copies stuff over to DS UploadOptions( // upload options to DS IN LPWSTR ServerAddress, IN LPDHCP_OPTION_SCOPE_INFO ScopeInfo ) { DWORD Err, Resume, PrefMax, i, nRead, nTotal; LPDHCP_ALL_OPTION_VALUES Options; Resume = 0; PrefMax = 0xFFFFFFFF; nRead = nTotal = 0; Options = NULL; Err = DhcpGetAllOptionValues( // get list of default opt values ServerAddress, 0, ScopeInfo, &Options ); if( ERROR_NO_MORE_ITEMS == Err ) return ERROR_SUCCESS; if( ERROR_SUCCESS != Err ) return Err; // oops could not do this simple task? for( i = 0; i < Options->NumElements; i ++ ) {// now try to set each list of options.. if( NULL == Options->Options[i].OptionsArray ) { continue; // uh? another way to say no options.. } Err = DhcpSetOptionValuesV5DS ( ServerAddress, Options->Options[i].IsVendor? DHCP_FLAGS_OPTION_IS_VENDOR:0, Options->Options[i].ClassName, Options->Options[i].VendorName, ScopeInfo, Options->Options[i].OptionsArray ); if( ERROR_SUCCESS != Err ) { MemFree(Options); return Err; } } return ERROR_SUCCESS; // saved it } //DOC ServerUploadOptions does rpc calls to server and copies stuff over to DS DWORD ServerUploadOptions( // upload options info to DS IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container to store at IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerAddress // server ip address ) { DWORD Err; DHCP_OPTION_SCOPE_INFO ScopeInfo; #if 0 ScopeInfo.ScopeInfo.DefaultScopeInfo = NULL; ScopeInfo.ScopeType = DhcpDefaultOptions; Err = UploadOptions(ServerAddress, &ScopeInfo); if( ERROR_SUCCESS != Err ) return Err; // could not save default options.. #endif ScopeInfo.ScopeType = DhcpGlobalOptions; ScopeInfo.ScopeInfo.GlobalScopeInfo = NULL; Err = UploadOptions(ServerAddress, &ScopeInfo); if( ERROR_SUCCESS != Err ) return Err; // could not save global options.. return ERROR_SUCCESS; } //DOC ReservationUploadOptions does rpc calls to server and copies stuff to DS DWORD ReservationUploadOptions( // upload reservation options to DS IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container to store at IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerAddress, // server ip address IN DWORD SubnetAddress, // add of subnet to add IN DWORD ReserveAddress // address of reservation ) { DHCP_OPTION_SCOPE_INFO ScopeInfo; ScopeInfo.ScopeType = DhcpReservedOptions; ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpSubnetAddress = SubnetAddress; ScopeInfo.ScopeInfo.ReservedScopeInfo.ReservedIpAddress = ReserveAddress; return UploadOptions(ServerAddress, &ScopeInfo); } //DOC SubnetUploadOptions does rpc calls to server and copies stuff to DS DWORD SubnetUploadOptions( // upload subnet options to DS IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container to store at IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerAddress, // server ip address IN DWORD SubnetAddress // add of subnet to add ) { DHCP_OPTION_SCOPE_INFO ScopeInfo; ScopeInfo.ScopeType = DhcpSubnetOptions; ScopeInfo.ScopeInfo.SubnetScopeInfo = SubnetAddress; return UploadOptions(ServerAddress, &ScopeInfo); } //DOC ServerUploadSubnet does rpc calls to server and copies stuff over to DS DWORD ServerUploadSubnet( // upload subnet and relevant info to DS IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container to store at IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerAddress, // server ip address IN DWORD SubnetAddress // add of subnet to add ) { DWORD Err, Resume, PrefMax, i, nRead, nTotal; LPDHCP_SUBNET_INFO SubnetInfo; DHCP_SUBNET_ELEMENT_TYPE SubnetEltType; LPDHCP_SUBNET_ELEMENT_INFO_ARRAY_V4 EltInfo; LPDHCP_SUPER_SCOPE_TABLE SScopeTbl; Err = DhcpGetSubnetInfo(ServerAddress, SubnetAddress, &SubnetInfo); if( ERROR_SUCCESS != Err ) return Err; // could not get subnet info.. Err = DhcpCreateSubnetDS(ServerAddress, SubnetAddress, SubnetInfo); if( SubnetInfo ) MemFree(SubnetInfo); if( ERROR_SUCCESS != Err ) return Err; // could not save onto DS SScopeTbl = NULL; Err = DhcpGetSuperScopeInfoV4( // get superscope table ServerAddress, &SScopeTbl ); if( ERROR_SUCCESS == Err ) { // could get superscope table for( i = 0; i < SScopeTbl->cEntries ; i ++ ) { if( SScopeTbl->pEntries[i].SubnetAddress == SubnetAddress ) { Err = DhcpSetSuperScopeV4DS( ServerAddress, SubnetAddress, SScopeTbl->pEntries[i].SuperScopeName, TRUE /* change superscope if it exists..*/ ); break; } } MemFree(SScopeTbl); if( ERROR_SUCCESS != Err ) return Err; // could not set superscope.. } Resume = 0; PrefMax = 0xFFFFFFFF; EltInfo = NULL; nRead = nTotal = 0; Err = DhcpEnumSubnetElementsV4( // enumerate ranges ServerAddress, SubnetAddress, DhcpIpRanges, &Resume, PrefMax, &EltInfo, &nRead, &nTotal ); if( ERROR_SUCCESS != Err ) return Err; // could not get ranges for( i = 0; i < EltInfo->NumElements; i ++ ) {// try to add each range Err = DhcpAddSubnetElementV4DS( ServerAddress, SubnetAddress, &EltInfo->Elements[i] ); if( ERROR_SUCCESS != Err ) break; } if( EltInfo ) MemFree(EltInfo); // free-up memory if( ERROR_SUCCESS != Err ) return Err; // could not add ranges Resume = 0; PrefMax = 0xFFFFFFFF; EltInfo = NULL; Err = DhcpEnumSubnetElementsV4( // enumerate reservations ServerAddress, SubnetAddress, DhcpReservedIps, &Resume, PrefMax, &EltInfo, &nRead, &nTotal ); if( ERROR_NO_MORE_ITEMS == Err ) goto try_Excl; if( ERROR_SUCCESS != Err ) return Err; // could not get exclusions for( i = 0; i < EltInfo->NumElements; i ++ ) {// try to add each reservation Err = DhcpAddSubnetElementV4DS( ServerAddress, SubnetAddress, &EltInfo->Elements[i] ); if( ERROR_SUCCESS != Err ) break; // could not add reseration in DS Err = ReservationUploadOptions( hDhcpC, hServer, ServerAddress, SubnetAddress, EltInfo->Elements[i].Element.ReservedIp->ReservedIpAddress ); if( ERROR_SUCCESS != Err ) break; // could not add reservaation options } if( EltInfo ) MemFree(EltInfo); // free-up memory if( ERROR_SUCCESS != Err ) return Err; // could not add exclusions try_Excl: Resume = 0; PrefMax = 0xFFFFFFFF; EltInfo = NULL; Err = DhcpEnumSubnetElementsV4( // enumerate exclusions ServerAddress, SubnetAddress, DhcpReservedIps, &Resume, PrefMax, &EltInfo, &nRead, &nTotal ); if( ERROR_NO_MORE_ITEMS == Err ) goto try_Options; if( ERROR_SUCCESS != Err ) return Err; // could not get exclusions for( i = 0; i < EltInfo->NumElements; i ++ ) {// try to add each exclusion Err = DhcpAddSubnetElementV4DS( ServerAddress, SubnetAddress, &EltInfo->Elements[i] ); if( ERROR_SUCCESS != Err ) break; } if( EltInfo ) MemFree(EltInfo); // free-up memory if( ERROR_SUCCESS != Err ) return Err; // could not add exclusions try_Options: return SubnetUploadOptions(hDhcpC,hServer,ServerAddress,SubnetAddress); } //DOC ServerUploadSubnets does rpc calls to server and copies stuff over to DS DWORD ServerUploadSubnets( // upload subnets info to DS IN OUT LPSTORE_HANDLE hDhcpC, // dhcp container to store at IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerAddress // server ip address ) { DWORD Err, Resume, PrefMax, i, nRead, nTotal; LPDHCP_IP_ARRAY Subnets; Resume = 0; PrefMax = 0xFFFFFFFF; nRead = nTotal = 0; Subnets = NULL; Err = DhcpEnumSubnets(ServerAddress, &Resume, PrefMax, &Subnets, &nRead, &nTotal); if( ERROR_NO_MORE_ITEMS == Err ) return ERROR_SUCCESS; if( ERROR_SUCCESS != Err ) return Err; // could not get list of elements? for( i = 0; i < Subnets->NumElements ; i ++ ) { Err = ServerUploadSubnet(hDhcpC, hServer, ServerAddress, Subnets->Elements[i]); if( ERROR_SUCCESS != Err ) break; } if( Subnets ) MemFree(Subnets); return Err; } //DOC UploadServer downloads the server info by making RPC calls.. DWORD UploadServer( // make rpc calls and pull up info to DS. IN OUT LPSTORE_HANDLE hDhcpC, // general container where info is stored IN OUT LPSTORE_HANDLE hServer, // server obj in DS IN LPWSTR ServerName, // name of server IN DWORD IpAddress // ip address of server ) { DWORD Err; LPSTR IpAddrStr; WCHAR ServerAddress[sizeof("000.000.000.000")]; IpAddress = htonl(IpAddress); // use n/w order ip address.. IpAddrStr = inet_ntoa(*(struct in_addr *)&IpAddress); Err = mbstowcs(ServerAddress, IpAddrStr, ( sizeof(ServerAddress)/sizeof( WCHAR ) ) ); if( -1 == Err ) { // could not convert to LPWSTR return ERROR_GEN_FAILURE; } Err = ServerUploadClasses(hDhcpC, hServer, ServerAddress); if( ERROR_SUCCESS != Err ) { // could not upload server classes info return Err; } Err = ServerUploadOptdefs(hDhcpC, hServer, ServerAddress); if( ERROR_SUCCESS != Err ) { // could not upload option defs ? return Err; } Err = ServerUploadOptions(hDhcpC, hServer, ServerAddress); if( ERROR_SUCCESS != Err ) { // could not upload options? return Err; } Err = ServerUploadSubnets(hDhcpC, hServer, ServerAddress); if( ERROR_SUCCESS != Err ) { // could not upload subnets? return Err; } return ERROR_SUCCESS; } //BeginExport(function) //DOC AddServer should add the new address to the server's attribs //DOC it should take this opportunity to reconcile the server. //DOC Currently it does nothing. (at the least it should probably try to //DOC check if the object exists, and if not create it.) //DOC DWORD AddServer( // add server and do misc work IN OUT LPSTORE_HANDLE hDhcpC, // container for server obj IN LPWSTR ServerName, // [DNS?] name of server IN LPWSTR ADsPath, // ADS path to server object IN DWORD IpAddress, // IpAddress to add to server IN DWORD State // state of server ) //EndExport(function) { DWORD Err, Err2; STORE_HANDLE hServer; Err = StoreGetHandle( // get the server obj.. hDhcpC, DDS_RESERVED_DWORD, StoreGetChildType, ADsPath, &hServer ); if( ERROR_SUCCESS != Err ) return Err; // could be because server obj elsewhere?? if( !CFLAG_DONT_DO_DSWORK ) { // if DS stuff is enabled in the first place Err = UploadServer(hDhcpC, &hServer, ServerName, IpAddress); } StoreCleanupHandle(&hServer, 0); // cleanup this server.. return Err; } //================================================================================ // end of file //================================================================================