dhcpinit.c

来自「wince下的源代码集合打包」· C语言 代码 · 共 470 行

C
470
字号
/*++Copyright (c) 1994-2000 Microsoft Corporation.  All rights reserved.Module Name:    init.cAbstract:    This is the main routine for the DHCP client.Environment:    User Mode - Win32Revision History:--*/#include <dhcpcli.h>#include <stdio.h>#ifndef VXD#include <..\newnt\dhcploc.h>#endif//// Internal function prototypes//DWORDDhcpInitialize(    LPDWORD SleepTime    )/*++Routine Description:    This function initializes DHCP.  It walks the work list looking for    address to be acquired, or to renew.  It then links the DHCP context    block for each card on the renewal list.Arguments:    None.Return Value:    minTimeToSleep - The time before the until DHCP must wake up to renew,        or reattempt acquisition of an address.    -1 - DHCP could not initialize, or no cards are configured for DHCP.--*/{    DWORD Error;    PDHCP_CONTEXT dhcpContext;    PLIST_ENTRY listEntry;    DWORD minTimeToSleep = (DWORD)-1;    DWORD timeToSleep;    //    // Perform Global (common) variables initialization.    //#ifdef  __DHCP_DYNDNS_ENABLED__#ifdef DBG    // initialize the debug build of dnslib    DnsStartDebug( 0, NULL, NULL, NULL, NULL );#endif#endif    DhcpGlobalProtocolFailed = FALSE;    //    // Perform local initialization    //    Error = SystemInitialize();    if ( Error != ERROR_SUCCESS ) {        DhcpPrint(( DEBUG_ERRORS, "System initialize failed, %ld.\n", Error ));        minTimeToSleep = (DWORD)-1;        goto Cleanup;    }    //    // ?? Introduce Random delay between 0 to 10 seconds    // to desynchronize the use of DHCP at startup.    //    //    // Loop through the list of installed cards, and attempt to renew    // or acquire leases.    //    for ( listEntry = DhcpGlobalNICList.Flink;            listEntry != &DhcpGlobalNICList;                listEntry = listEntry->Flink ) {        dhcpContext =            CONTAINING_RECORD( listEntry, DHCP_CONTEXT, NicListEntry );        DhcpPrint(( DEBUG_LEASE,            "Old IpAddress %s\n",                inet_ntoa(*(struct in_addr *)&dhcpContext->IpAddress) ));        DhcpPrint(( DEBUG_LEASE,            "Old lease obtained %s", ctime(&dhcpContext->LeaseObtained) ));        DhcpPrint(( DEBUG_LEASE,            "Old lease expires  %s", ctime(&dhcpContext->LeaseExpires) ));        if ( DhcpIsInitState( dhcpContext ) )        {            Error = ReObtainInitialParameters( dhcpContext, &timeToSleep );            if ( (Error != ERROR_SUCCESS) &&                    (Error != ERROR_SEM_TIMEOUT) &&                        (Error != ERROR_ACCESS_DENIED) &&                            (Error != ERROR_DHCP_ADDRESS_CONFLICT ) ) {                minTimeToSleep = (DWORD)-1;                goto Cleanup;            }        } else {            //            // Otherwise verify lease.            //            Error = ReRenewParameters( dhcpContext, &timeToSleep );            if ( (Error != ERROR_SUCCESS) &&                    (Error != ERROR_SEM_TIMEOUT) &&                        (Error != ERROR_ACCESS_DENIED) &&                            ( Error != ERROR_DHCP_ADDRESS_CONFLICT )) {                minTimeToSleep = (DWORD)-1;                goto Cleanup;            }        }#ifndef VXD        UpdateStatus();     // send heart beat to SC.#endif        minTimeToSleep = MIN( minTimeToSleep, timeToSleep );        //        // this adapter has been processed by the dhcp client. flag the adapter        // accordingly.        //#ifdef __DHCP_DYNDNS_ENABLED__        dhcpContext->fFlags |= DHCP_CONTEXT_FLAGS_PROCESSED;#endif    }#ifdef __DHCP_DYNDNS_ENABLED__    //    // if a dynamic dns update still needs to be done, do it now.  Normally,    // the update would have been performed when the last dhcp adapter in the    // list was processed above.  However, if processing for this adapter failed    // for some reason ( e.g. the dhcp server couldn't be updated ) then we need    // to do the update now.    //        if ( DhcpIsDynamicDNSEnabled() )    {        DhcpUpdateDns( NULL, FALSE );    }#endif    Error = ERROR_SUCCESS;Cleanup:    if( SleepTime != NULL ) {        *SleepTime = minTimeToSleep;    }#ifdef __DHCP_DYNDNS_ENABLED__#ifdef DBG    if ( ERROR_SUCCESS != Error )    {        DnsEndDebug();    }#endif#endif    return( Error );}DWORDCalculateTimeToSleep(    PDHCP_CONTEXT DhcpContext    )/*++Routine Description:    Calculate the amount of time to wait before sending a renewal,    or new address request.    Algorithm:        //        // ?? check retry times.        //        If Current-Ip-Address == 0            TimeToSleep = ADDRESS_ALLOCATION_RETRY            UseBroadcast = TRUE        else if the lease is permanent            TimeToSleep = INFINIT_LEASE            UseBroadcast = TRUE        else if the time now is < T1 time            TimeToSleep = T1 - Now            UseBroadcast = FALSE        else  if the time now is < T2 time            TimeToSleep = Min( 1/8 lease time, MIN_RETRY_TIME );            UseBroadcast = FALSE        else if the time now is < LeaseExpire            TimeToSleep = Min( 1/8 lease time, MIN_RETRY_TIME );            UseBroadcast = TRUEArguments:    RenewalContext - A pointer to a renewal context.Return Value:    TimeToSleep - Returns the time to wait before sending the next        DHCP request.    This routine sets DhcpContext->DhcpServer to -1 if a broadcast    should be used.--*/{    time_t TimeNow;    //    // if there is no lease.    //    if ( DhcpContext->IpAddress == 0 ) {        // DhcpContext->DhcpServerAddress = (DHCP_IP_ADDRESS)-1;        return( ADDRESS_ALLOCATION_RETRY );    }    //    // if the lease is permanent.    //    if ( DhcpContext->Lease == INFINIT_LEASE ) {        return( INFINIT_TIME );    }    TimeNow = time( NULL );    //    // if the time is < T1    //    if( TimeNow < DhcpContext->T1Time ) {        return ( DhcpContext->T1Time - TimeNow );    }    //    // if the time is between T1 and T2.    //    if( TimeNow < DhcpContext->T2Time ) {        //        // wait half of the ramaining time but minimum of        // MIN_TIME_SLEEP secs.        //        return( MAX( ((DhcpContext->T2Time - TimeNow) / 2),                        MIN_SLEEP_TIME ) );    }    //    // if the time is between T2 and LeaseExpire.    //    if( TimeNow < DhcpContext->LeaseExpires ) {        DhcpContext->DhcpServerAddress = (DHCP_IP_ADDRESS)-1;        //        // wait half of the ramaining time but minimum of        // MIN_SLEEP_TIME secs.        //        return( MAX( ((DhcpContext->LeaseExpires - TimeNow) / 2),                        MIN_SLEEP_TIME ) );    }    //    // Lease has Expired.    //    // DhcpContext->IpAddress = 0;    return( MIN_SLEEP_TIME );}DWORDInitializeDhcpSocket(    SOCKET *Socket,    DHCP_IP_ADDRESS IpAddress    )/*++Routine Description:    This function initializes and binds a socket to the specified IP address.Arguments:    Socket - Returns a pointer to the initialized socket.    IpAddress - The IP address to bind the socket to.  It is legitimate        to bind a socket to 0.0.0.0 if the card has no current IP address.Return Value:    The status of the operation.--*/{    DWORD error;    DWORD closeError;    DWORD value;    struct sockaddr_in socketName;    DWORD i;    SOCKET sock;    //    // Sockets initialization    //    sock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );    if ( sock == INVALID_SOCKET ) {        error = WSAGetLastError();        DhcpPrint(( DEBUG_ERRORS, "socket failed, error = %ld\n", error ));        return( error );    }    //    // Make the socket share-able    //    value = 1;    error = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, (char FAR *)&value, sizeof(value) );    if ( error != 0 ) {        error = WSAGetLastError();        DhcpPrint((DEBUG_ERRORS, "setsockopt failed, err = %ld\n", error ));        closeError = closesocket( sock );        if ( closeError != 0 ) {            DhcpPrint((DEBUG_ERRORS, "closesocket failed, err = %d\n", closeError ));        }        return( error );    }    error = setsockopt( sock, SOL_SOCKET, SO_BROADCAST, (char FAR *)&value, sizeof(value) );    if ( error != 0 ) {        error = WSAGetLastError();        DhcpPrint((DEBUG_ERRORS, "setsockopt failed, err = %ld\n", error ));        closeError = closesocket( sock );        if ( closeError != 0 ) {            DhcpPrint((DEBUG_ERRORS, "closesocket failed, err = %d\n", closeError ));        }        return( error );    }    //    // If the IpAddress is zero, set the special socket option to make    // stack work with zero address.    //#ifdef VXD    if( IpAddress == 0 ) {#else        if( (IpAddress == 0 ) && (DhcpGlobalIsService == TRUE) ) {#endif        value = 1234;        error = setsockopt( sock, SOL_SOCKET, 0x8000, (char FAR *)&value, sizeof(value) );        if ( error != 0 ) {            error = WSAGetLastError();            DhcpPrint((DEBUG_ERRORS, "setsockopt failed, err = %ld\n", error ));            closeError = closesocket( sock );            if ( closeError != 0 ) {                DhcpPrint((DEBUG_ERRORS, "closesocket failed, err = %d\n", closeError ));            }            return( error );        }    }    socketName.sin_family = PF_INET;    socketName.sin_port = htons( DHCP_CLIENT_PORT );    socketName.sin_addr.s_addr = IpAddress;    for ( i = 0; i < 8 ; i++ ) {        socketName.sin_zero[i] = 0;    }    //    // Bind this socket to the DHCP server port    //    error = bind(               sock,               (struct sockaddr FAR *)&socketName,               sizeof( socketName )               );    if ( error != 0 ) {        error = WSAGetLastError();        DhcpPrint((DEBUG_ERRORS, "bind failed, err = %ld\n", error ));        closeError = closesocket( sock );        if ( closeError != 0 ) {            DhcpPrint((DEBUG_ERRORS, "closesocket failed, err = %d\n", closeError ));        }        return( error );    }    *Socket = sock;    return( NO_ERROR );}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?