⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp_proxy.c

📁 dhcp proxy,在电信设备中的运用
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 * dhcp_proxy.c - DHCP/BOOTP Process
 *
 *
 * Description: DHCP Proxy IP Address Assignment protocol and related routines
 * of the DHCP Process.
 *
 * Author(s): WEISHEIN FU, Kalyan Venkataramanan
 *
 *  +----------------------------------------------------------------------+
 *  | Copyright (c) 2003 UTStarcom Incorporated. All Rights Reserved.      |
 *  |                                                                      |
 *  | The information in this software is subject to change without notice |
 *  | and should not be construed as a commitment by UTStarcom  |
 *  | Corp.                                                                |
 *  |                                                                      |
 *  | UTStarcom Incorporated assumes no responsibility for the use or  |
 *  | reliability of its software on equipment which is not supplied by    |
 *  | UTStarcom.                                           |
 *  |                                                                      |
 *  | This software is furnished under a license and may be copied only    |
 *  | with the inclusion of the above copyright notice. This software, or  |
 *  | any other copies thereof, may not be provided or otherwise made      |
 *  | available to any other person except to one who agrees to these      |
 *  | license terms. Title to and ownership of the software shall at all   |
 *  | times remain in UTStarcom.                           |
 *  +----------------------------------------------------------------------+
 **
 **   Edit       Date            Author
 **   001        30-Mar-98       Weishein Fu
 **   002        02-Feb-99       Kalyan Venkataramanan
 **   003        02-Oct-99       Kalyan Venkataramanan
 **
 */

#include "usr_header.h"
#include "RoboExec.h"
#include "pilgrim.h"
#include <config.h>
#include <types.h>
#include <timer.h>
#include "attache.h"
#include "netaddr.h"
#include "InterfaceCB.h"
#include "network.h"
#include "drv_if.h"
#include "portal.h"
#include <net.h>
#include <route.h>
#include <ip.h>
#include "ip_if.h"
#include "forwarder.h"
#include "udp_if.h"
#include "udp_process.h"
#include <udp.h>

#include "managed.h"
#include "PlmIpMib_if.h"
#include "mib.h"
#include "dhcp_mib.h"

#include "bootp.h"
#include "dhcp_strings.h"
#include "dhcp_server.h"
#include "dhcp_proxy.h"

extern EventLevel Dhcp_trace_level;

#define  DHCP_DEBUG   if(Dhcp_trace_level==EVL_DEBUG)execp_printf

#define MAX_INT      65536
#define NO_OFFSET 	-1

#define BOOTP_OP_CODE_REQUEST		1
#define BOOTP_OP_CODE_REPLY		2
/* Bootp and Rarp protocol constants */
#define HW_TYPE_ETHERNET	1
#define HW_LEN_ETHERNET		6

#define VENDOR_INFO_LEN     64
#define MIN_DHCP_PACKET_SIZE	236	/* Only upto giaddr */

DHCP_CB *dhcp_array_cb = NULL;	/* array of Control Blocks */
Int32 num_of_dhcp_pcb_allocated = DHCP_PROXY_ALLOC;
Boolean DHCPProxyEnabled = DHCP_DISABLED;	/* Set it from CLI */
Boolean my_mac_resolved = FALSE;
Boolean my_ip_resolved = FALSE;
Boolean ProxyDiscIfLeaseExp = DHCP_DISABLED;
Int32 num_of_dhcp_pcb = 0;


static Boolean DHCP_TimerProc_ReplyMsg (void *);
static Boolean DHCP_TimerProc_ProxyIpMsg (void *);

void dhcp_proxy_init (DHCPPrivateData_t *, ExecStatus *);
void DHCP_proxy_del_ip (ExecMsg);

void DHCP_proxy_req_proc (ExecMsg, ExecStatus, DHCPPrivateData_t *, DhcpIPReqMsg *);
void dhcp_proxy_rcv_msg (ExecMsg, ExecStatus, DHCPPrivateData_t *, UdpRxMsg_t *);
static DHCP_ERROR_CODE DHCP_SendReq (Uint8 DHCP_MsgType, DHCP_CB * pCB, ExecBuff pBD,
									 Uint32 DestIpAddr, Boolean StoreSrvrID, Boolean ReTx,
									 ExecMsg req_msg, DHCPPrivateData_t * dhcp_private);

static void DHCP_fsm (DHCP_CB *, ExecBuff, DHCP_PKT *, Uint8, DHCPPrivateData_t *);

void DHCP_StoreOp (Uint8 OpCode, Uint8 Len, Uint8 * pVal, Uint8 * pBuf, Uint32 LenLimit,
				   Boolean Swap_Word);
static Boolean DHCP_GetOp (Uint8 * pSrc, Uint8 * pDest, Uint8 OpCode, Uint32 LenLimit,
						   Boolean Swap_Word);
static DHCP_ERROR_CODE DHCP_GetAllOps (DHCP_PKT *, DHCP_CB *, Uint8, Uint32);

static DHCP_CB *DHCP_GetCB (Uint32);
static DHCP_CB *DHCP_GetFreeCB (void);
static void DHCP_FreeCB (DHCP_CB *);
static void DHCP_Release (DHCP_CB *);
Uint32 DHCP_get_src_ip_address (void);
void DHCP_get_my_mac_addr (ExecMsg msg);
void DHCP_delete_ondemand (DHCP_CB *);

/* CLI hidden commands */
void dhcp_proxy_get_active_pcb (void);
void dhcp_del_active_pcb (int);

MacAddr_t my_mac_addr;
Uint32 SrcIpAddr;

#define ProxyAddStringOption(o, op, c, s)    ProxyAddMemOption(o, op, c, s, strlen(s)+1)
static void ProxyAddSimpleOption (Uint8 * Options, int *p_Offset, Uint8 Code, Uint8 Value);
static void ProxyAddMemOption (Uint8 * Options, int *p_Offset, Uint8 Code, char *Str, int Length);
static void ProxyAddULONGOption (Uint8 * Options, int *p_Offset, Uint8 Code, Uint32 Value);

/*
 * This function prepares the necessary parameters before calling the
 * main DHCP process: DHCP_fsm().
 */
void
DHCP_proxy_req_proc (ExecMsg msg, ExecStatus status, DHCPPrivateData_t * dhcp_private,
					 DhcpIPReqMsg * dhcpproxy_params)
{
	DHCP_CB *pCB;
	DHCP_CB *parm1;				/* pCB if func=START_CYCLE */
	Uint8 parm4;				/* DHCP Packet Type if exist */

	ArpResolveAddrMsg *arp_resolve_param;
	ExecMsg arp_resolve_msg;


	DHCP_DEBUG ("DHCP_proxy_req_proc(): dhcpproxy_params->msgtype %d\n",
				dhcpproxy_params->dhcp_msgtype);

	/* check all flags ie. DhcpProxyEnabled, etc. */
	if (!DHCPProxyEnabled) {
		DHCP_DEBUG ("DHCP_proxy_req_proc(): DHCPProxy is not Enabled !\n");

		/* TODO
		 ** Have to actually return error message back to IP.
		 ** As of now just returning IP of 0.0.0.0
		 */
		SETu32 (&dhcpproxy_params->framed_ip_address, 0);

		DHCP_DEBUG ("dhcp_fsm(): Respond to IP with %ai\n", &dhcpproxy_params->framed_ip_address);

		DHCP_DEBUG ("Responding to sender %s\n", exec_get_process_name (EXEC_GET_MSG_SENDER (msg)));

		exec_respond_to_msg (msg, IP_FWD_DHCP_IPADDR_RSP, ES_SUCCESS, DEFAULT_FLAGS);

		return;
	}

	if (!my_ip_resolved) {

		/* IP ADDRESS */
		if ((SrcIpAddr = DHCP_get_src_ip_address ()) == 0) {
			exec_resolve_name (IP_HOST_ADDRESS_NAME, &SrcIpAddr, NULL, NMF_STD_ERROR, 0);
		}
		DHCP_DEBUG ("DHCP_get_src_ip_address returns %ai for ARP\n", &SrcIpAddr);

		my_ip_resolved = TRUE;
	}

	if (!my_mac_resolved) {
		arp_resolve_msg = exec_alloc_msg (sizeof (ArpResolveAddrMsg),
										  ARP_RESOLVE_IP_ADDRESS_REQ, DEFAULT_FLAGS, &status);

		arp_resolve_param = EXEC_GET_MSG_PARAM (arp_resolve_msg);
		arp_resolve_param->addr_to_be_resolved = SrcIpAddr;

		/*
		 ** Set flag to indicate that an ARP is required even if the
		 ** cache entry is complete.
		 */
		arp_resolve_param->flags = 1;

		DHCP_DEBUG ("DHCP_proxy_req_proc(): Send ARP_RESOLVE_IP_ADDRESS_REQ \n");

		status = exec_sendmsg (arp_resolve_msg, dhcp_private->ip_fwd_mbox, DEFAULT_FLAGS);
		if (status != ES_SUCCESS) {
			DHCP_DEBUG ("DHCP_PROXY: Could not send ARP_RESOLVE_IP_ADDRESS_REQ message : (%E)\n",
						status);
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_DEBUG, DHCP_STRINGS,
						STRING_NUM (dhcp_error_passmsg), status);
			exec_freemsg (arp_resolve_msg, DEFAULT_FLAGS);
		}
	}

	pCB = DHCP_GetFreeCB ();
	/*
	 * Calling function must have received a BOOTP/RARP/SLIP request.
	 * Only start the cycle if CB is not processing any BOOTP/RARP/SLIP
	 * request.
	 */

	if (pCB->ProxyTimerSet || (pCB->State != DHCP_STATE_INIT)) {
		DHCP_DEBUG ("DHCP_fsm(): TimerSet || State != DHCP_STATE_INIT - STOP ");
		DHCP_FreeCB ((DHCP_CB *) pCB);
		/* Must be a BOOTP/RARP retransmitted request */
		return;
	}
	pCB->msg = msg;				/* DhcpIPReqMsg msg from ip_ondemand.c */

	pCB->dhcp_connection_id = dhcpproxy_params->dhcp_connection_id;

	parm1 = pCB;
	parm4 = dhcpproxy_params->dhcp_msgtype;
	/* Call the DHCP state machine */
	DHCP_fsm (parm1, NULL, (DHCP_PKT *) NULL, (Uint8) parm4, dhcp_private);
}


/*
 * This is the main process. It either sends out a DHCP request or receives a
 * DHCP reply depending on the state.
 */
void
DHCP_fsm (DHCP_CB * pCB, ExecBuff pBD, DHCP_PKT * pDhcpHdr, Uint8 DHCP_MsgType,
		  DHCPPrivateData_t * dhcp_private)
{
	Uint32 Offered_IpAddr;
	DHCP_ERROR_CODE RetCode = E_NONE;
	ExecMsg req_msg;
	ExecStatus status = ES_SUCCESS;
	DhcpIPReqMsg *param;
	Int8 ClientPrefix[20] = "HiperClient\0";

	DHCP_DEBUG ("DHCP_fsm(): Recd. DHCP_MsgType %d \n", DHCP_MsgType);

	/* This condition serves no real purpose... just safety... */
	if ((pDhcpHdr != NULL) && (pDhcpHdr->Xid != pCB->Xid)) {
		/* DHCP pkt does not match with pCB */
		DHCP_DEBUG ("DHCP_fsm(): Xid mismatch, something weird \n");
		exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
					STRING_NUM (dhcp_proxy_xid_nomatch), status);
		return;
	}

	switch (pCB->State) {

	case DHCP_STATE_INIT:
		DHCP_DEBUG ("DHCP_fsm(): DHCP_STATE_INIT \n");
		/* Start of the state machine */
		/* Assign a desired lease time */

		pCB->LeaseTime = ~0UL;	/* max out */

		exec_sprintf (pCB->ClientID, "%x%ld", my_mac_addr.enet_addr, pCB->dhcp_connection_id);
		DHCP_DEBUG ("DHCP_fsm(): pCB->ClientID : %s\n", pCB->ClientID);

		exec_sprintf (pCB->ClientHostName, "%s%ld", ClientPrefix, pCB->dhcp_connection_id);
		DHCP_DEBUG ("DHCP_fsm(): pCB->ClientHostName : %s\n", pCB->ClientHostName);

		/* prepare broadcast UDP message for DHCP_DISCOVER */
		req_msg = exec_alloc_msg (sizeof (UdpTxMcastPktMsg),
								  UDP_MCAST_SEND_REQ, DEFAULT_FLAGS, &status);
		if (req_msg == NULL || status != ES_SUCCESS) {
			DHCP_FreeCB ((DHCP_CB *) pCB);
			/* proxyed to get message. Generate an event */
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
						STRING_NUM (dhcp_error_alloc_msg), status);
			return;
		}

		/* Send a DHCP_DISCOVER to solicit OFFERs from DHCP servers */
		if ((RetCode = DHCP_SendReq (DHCP_DISCOVER, pCB, NULL, 0xffffffff,
									 FALSE, TRUE, req_msg, dhcp_private)) != E_NONE) {
			exec_freemsg (req_msg, DEFAULT_FLAGS);
			DHCP_FreeCB ((DHCP_CB *) pCB);
			/* Failed to get message. Generate an event */
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
						STRING_NUM (dhcp_error_udp_sendmsg), status);
			return;
		}

		dhcp_private->proxy_count.discover_sent++;

		pCB->State = DHCP_STATE_SELECT;
		pCB->udp_mbox = dhcp_private->udp_mbox;
		pCB->TimerType = DHCP_MSG_WAIT4REPLY_TIMEOUT;

		/* Retry timer */
		DHCP_DEBUG ("DHCP_fsm(): Starting DHCP_WAIT4REPLY_TIMEOUT in state %d\n", pCB->State);
		pCB->DhcpWait4ReplyMsg = exec_set_alarm (DHCP_TimerProc_ReplyMsg, (void *) pCB->Xid,
												 MAGIC_NUMBER ('D', 'P', 'T', 'R'),
												 DHCP_WAIT4REPLY_TIMEOUT, TMRF_SECONDS, &status);
		if (status != ES_SUCCESS) {
			pCB->DhcpWait4ReplyMsg = NULL;
			DHCP_FreeCB ((DHCP_CB *) pCB);
			exec_Event (PEVT_DHCP, EVT_ALLSINKS,
						EVL_UNUSUAL, DHCP_STRINGS,
						STRING_NUM (dhcp_fail_set_proxy_retry_timer), status);
			return;
		}

		/* Start timer for Proxy IP addr timeout */
		DHCP_DEBUG ("DHCP_fsm():Starting DHCP_PROXYIP_TIMEOUT \n");

		if (!pCB->ProxyTimerSet) {
			pCB->TimerTypeProxy = DHCP_MSG_PROXYIPADDR_TIMEOUT;
			pCB->DhcpProxyIPMsg = exec_set_alarm (DHCP_TimerProc_ProxyIpMsg,
												  (void *) pCB->Xid, MAGIC_NUMBER ('D', 'P', 'T',
																				   'I'),
												  DHCP_PROXYIP_TIMEOUT, TMRF_SECONDS, &status);
			if (status != ES_SUCCESS) {
				pCB->DhcpProxyIPMsg = NULL;
				DHCP_FreeCB ((DHCP_CB *) pCB);
				exec_Event (PEVT_DHCP, EVT_ALLSINKS,
							EVL_CRITICAL, DHCP_STRINGS,
							STRING_NUM (dhcp_fail_set_proxy_iptimer), status);
				return;
			}
			pCB->ProxyTimerSet = TRUE;
		}

		break;

	case DHCP_STATE_SELECT:

		DHCP_DEBUG ("DHCP_fsm(): DHCP_STATE_SELECT \n");

		if ((pBD != NULL) && (DHCP_MsgType != DHCP_OFFER)) {
			DHCP_DEBUG ("%s<%d>:  DHCP_STATE_SELECT Bad MsgType !\n", __FILE__, __LINE__);
			DHCP_DEBUG ("DHCP_fsm(): DHCP_MsgType != DHCP_OFFER, EXITING\n");

			return;
		}

		dhcp_private->proxy_count.offers++;

		if (DHCP_GetAllOps (pDhcpHdr, pCB, DHCP_MsgType, OPTIONS_LEN) != E_NONE) {
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_DEBUG, DHCP_STRINGS,
						STRING_NUM (dhcp_proxy_no_options), status);
			return;
		}

		/* Check for validity of the offered IP address */
		Offered_IpAddr = VALUE_NETORDu32 (pDhcpHdr->YourIpAddr);

		if (pCB->SavedpBD != NULL) {
			exec_free_bchain (pCB->SavedpBD, DEFAULT_FLAGS);
			pCB->SavedpBD = NULL;
			DHCP_DEBUG ("DHCP_fsm(): Got OFFER, Freeing Old Saved DISCOVER buffer\n");
		}

		/* prepare broadcast UDP message for sending DHCP_REQUEST */
		req_msg = exec_alloc_msg (sizeof (UdpTxMcastPktMsg),
								  UDP_MCAST_SEND_REQ, DEFAULT_FLAGS, &status);
		if (req_msg == NULL || status != ES_SUCCESS) {
			DHCP_FreeCB (pCB);
			/* Failed to get message. Generate an event */
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
						STRING_NUM (dhcp_error_alloc_msg), status);
			return;
		}

		/* Accept the offer */
		pCB->ClientIpAddr = Offered_IpAddr;
		pCB->YourIpAddr = Offered_IpAddr;

		/* Got a reply .. no need to retransmit .. Kill retry timer */
		if (pCB->DhcpWait4ReplyMsg != NULL) {
			exec_stop_timer (pCB->DhcpWait4ReplyMsg, TMRF_CHECK_MBOX);
			exec_freemsg (pCB->DhcpWait4ReplyMsg, DEFAULT_FLAGS);
			pCB->DhcpWait4ReplyMsg = NULL;	/* For DHCP_TimerProc() to stop it */
		}

		/* Use the received to send out DHCP_REQUEST */
		pCB->Retry = 1;

		/* Send a DHCP_REQUEST to acknowledge OFFER from a DHCP server */
		if ((RetCode = DHCP_SendReq (DHCP_REQUEST, pCB, NULL, 0xffffffff,
									 TRUE, TRUE, req_msg, dhcp_private)) != E_NONE) {
			exec_freemsg (req_msg, DEFAULT_FLAGS);
			DHCP_FreeCB ((DHCP_CB *) pCB);
			/* Failed to get message. Generate an event */
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
						STRING_NUM (dhcp_error_udp_sendmsg), status);
			/* Cannnot send request, return and wait for next chance */
			return;
		}

		pCB->udp_mbox = dhcp_private->udp_mbox;
		pCB->State = DHCP_STATE_REQ;
		pCB->TimerType = DHCP_MSG_WAIT4REPLY_TIMEOUT;

		DHCP_DEBUG ("DHCP_fsm(): Starting DHCP_WAIT4REPLY_TIMEOUT in state %d\n", pCB->State);
		pCB->DhcpWait4ReplyMsg = exec_set_alarm (DHCP_TimerProc_ReplyMsg, (void *) pCB->Xid,
												 MAGIC_NUMBER ('D', 'P', 'T', 'R'),
												 DHCP_WAIT4REPLY_TIMEOUT, TMRF_SECONDS, &status);
		if (status != ES_SUCCESS) {
			pCB->DhcpWait4ReplyMsg = NULL;
			DHCP_FreeCB ((DHCP_CB *) pCB);
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_CRITICAL, DHCP_STRINGS,
						STRING_NUM (dhcp_fail_set_proxy_retry_timer), status);
			return;
		}

		break;

	case DHCP_STATE_REQ:
	case DHCP_STATE_RENEW:
	case DHCP_STATE_REBIND:
		DHCP_DEBUG ("DHCP_fsm():DHCP_STATE_REQ/RENEW/REBIND \n");
		/* should be receiving the DHCP_ACK/DHCP_NAK reply from a
		   DHCP server */

		if ((pBD != NULL) && (DHCP_MsgType != DHCP_ACK) && (DHCP_MsgType != DHCP_NAK)) {
			DHCP_DEBUG ("DHCP_fsm(): DHCP_MsgType != ACK or NAK ! but :%d\n", DHCP_MsgType);
			return;
		}

		/* Got reply no need to retrans Kill retry timer */
		if (pCB->DhcpWait4ReplyMsg != NULL) {
			exec_stop_timer (pCB->DhcpWait4ReplyMsg, TMRF_CHECK_MBOX);
			exec_freemsg (pCB->DhcpWait4ReplyMsg, DEFAULT_FLAGS);
			pCB->DhcpWait4ReplyMsg = NULL;
		}

		if (pCB->SavedpBD != NULL) {
			exec_free_bchain (pCB->SavedpBD, DEFAULT_FLAGS);
			pCB->SavedpBD = NULL;
			DHCP_DEBUG ("DHCP_fsm(): Got ACK or NAK %d Freeing Old Saved REQUEST buffer\n",
						DHCP_MsgType);
		}

		if (DHCP_MsgType == DHCP_ACK) {
			/* DHCP server accepts the request from us */
			/* Get YourIpAddr */
			Offered_IpAddr = VALUE_NETORDu32 (pDhcpHdr->YourIpAddr);
			pCB->YourIpAddr = Offered_IpAddr;
			pCB->ClientIpAddr = Offered_IpAddr;

			/* Get all options from ACK pkt */
			if (DHCP_GetAllOps (pDhcpHdr, pCB, DHCP_MsgType, OPTIONS_LEN) != NO_ERROR) {

				exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_DEBUG, DHCP_STRINGS,
							STRING_NUM (dhcp_proxy_get_op_error), status);
				return;
			}

			if (pCB->State == DHCP_STATE_REQ) {
				DHCP_DEBUG ("DHCP_fsm(): DHCP_IPADDR_ACQUIRED \n");
				exec_Event (PEVT_DHCP, EVF_ALL_CONSOLES | EVF_SYSLOG, EVL_COMMON,
							DHCP_STRINGS, STRING_NUM (dhcp_proxy_ip_addr_acq), &Offered_IpAddr);
			}


			pCB->State = DHCP_STATE_BOUND;
			DHCP_DEBUG ("DHCP_fsm(): DHCP_STATE_BOUND \n");

			if ((pCB->msg != NULL) && (!pCB->ip_addr_acq)) {

⌨️ 快捷键说明

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