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

📄 dhcp_proxy.c

📁 dhcp proxy,在电信设备中的运用
💻 C
📖 第 1 页 / 共 4 页
字号:
		param = (DhcpIPReqMsg *) EXEC_GET_MSG_PARAM (pCB->msg);
		SETu32 (&param->framed_ip_address, 0);

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

		exec_respond_to_msg (pCB->msg, IP_FWD_DHCP_IPADDR_RSP, ES_SUCCESS, DEFAULT_FLAGS);
		pCB->ip_addr_acq = FALSE;
		pCB->msg = NULL;
	} else {
		DHCP_DEBUG ("DHCP_freeCB(): IP msg already responded..\n");
	}

	/*
	 ** Free up the associated saved buffer
	 */
	if (dhcp_array_cb[indexl].SavedpBD != NULL) {
		DHCP_DEBUG ("DHCP_FreeCB(): Freeing SavedpBD \n");
		exec_free_bchain (dhcp_array_cb[indexl].SavedpBD, DEFAULT_FLAGS);
		dhcp_array_cb[indexl].SavedpBD = NULL;
	}

	DHCP_DEBUG ("Releasing pCB indexl %d, IP %ai, Xid %u num = %d\n", indexl,
				&pCB->YourIpAddr, pCB->Xid, num_of_dhcp_pcb);

	if (((indexl == 0) && (num_of_dhcp_pcb == 1)) || (indexl == (num_of_dhcp_pcb - 1))) {
		dhcp_array_cb[indexl].Xid = 0;
		SETu32 (&dhcp_array_cb[indexl].YourIpAddr, 0);
		dhcp_array_cb[indexl].ProxyTimerSet = FALSE;
		dhcp_array_cb[indexl].ip_addr_acq = FALSE;
		dhcp_array_cb[indexl].State = DHCP_STATE_INIT;
	} else {
		/* Move everything below table_index entry up. */
		memmove (&dhcp_array_cb[indexl],
				 &dhcp_array_cb[indexl + 1], (num_of_dhcp_pcb - indexl - 1) * sizeof (DHCP_CB));
	}

	num_of_dhcp_pcb--;			/* decrement usage count */

	return;
}


/*
 * DHCP_StoreOp() stores the option value to the Option field of the
 * Bootp header. It assumes that there exists an END_OF_OPTION mark (255).
 */
void
DHCP_StoreOp (Uint8 OpCode, Uint8 Len, Uint8 * pVal, Uint8 * pBuf, Uint32 LenLimit, Boolean Swap_Word)
{
	Uint32 *pWDest;
	Uint32 *pWSrc;
	Uint8 *pChar;
	Uint8 i = 0;
	Uint8 j;

	pChar = pBuf;

	/* Get to end-of-option mark */
	/*
	 * Option has the format of:
	 *  Code (1 byte)   Len (1 Byte)    Option (Len bytes)
	 */
	while ((*pChar != DHCP_OP_ENDMARK) && (i < LenLimit)) {
		if (pChar[0] == 0) {
			/* Skip padding */
			i++;
			continue;
		}

		i += (pChar[1] + 2);
		pChar += (pChar[1] + 2);	/* Add Len to pChar to advance to next option */
	}

	if (i == LenLimit) {
		/* Options does not have end-mark */
		return;
	}

	/* Store Option code, len and value */
	*pChar++ = OpCode;
	*pChar++ = Len;
	if (Swap_Word) {
		pWDest = (Uint32 *) pChar;
		pWSrc = (Uint32 *) pVal;
		/*
		 *pWDest = VALUE_NETORDu32(*pWSrc);
		 COPY_NETORDu32( &pWDest, &pWSrc);
		 */

		*pWDest = VALUE_NETORDu32 (*pWSrc);
		pChar += Len;
	} else {
		for (j = 0; j < Len; j++) {
			*pChar++ = pVal[j];
		}
	}

	/* Mark end-of-option */
	*pChar = DHCP_OP_ENDMARK;
}


/*
 * DHCP_GetOp() retrieves the option specified by Opcode and returns it
 * to the calling function.
 */
Boolean
DHCP_GetOp (Uint8 * pSrc, Uint8 * pDest, Uint8 OpCode, Uint32 LenLimit, Boolean Swap_Word)
#if 0
	 BYTE *pSrc;
	 BYTE *pDest;
	 BYTE OpCode;
	 WORD LenLimit;
	 BOOLEAN Swap_Word;
#endif
{
	Uint32 *pWDest;
	Uint8 *pChar = pSrc;
	Uint8 i = 0;
	Uint8 Len;


	/*
	 * Option has the format of:
	 *  Code (1 byte)   Len (1 Byte)    Option (Len bytes)
	 */
	while ((*pChar != DHCP_OP_ENDMARK) && (i < LenLimit)) {
		if (pChar[0] == 0) {
			/* Skip padding */
			i++;
			continue;
		} else if (pChar[0] == OpCode) {
			/* Found the option */
			break;
		}

		i += (pChar[1] + 2);
		pChar += (pChar[1] + 2);	/* Add Len to pChar to advance to next option */
	}

	if ((*pChar == DHCP_OP_ENDMARK) || (i >= LenLimit)) {
		return (FALSE);
	}

	Len = pChar[1];
	pChar += 2;					/* now points to the option itself */
	for (i = 0; i < Len; i++) {
		pDest[i] = *pChar++;
	}

	if (Swap_Word) {
		pWDest = (Uint32 *) pDest;
		*pWDest = VALUE_NETORDu32 (pWDest[0]);
#if 0
		pWDest = (WORD *) pDest;
		*pWDest = SWAP_WORD (pWDest[0]);
#endif
	}

	return (TRUE);
}

/*
 * DHCP_GetAllOps() retrieves all options.
 */
DHCP_ERROR_CODE
DHCP_GetAllOps (DHCP_PKT * pDhcpHdr, DHCP_CB * pCB, Uint8 DHCP_MsgType, Uint32 LenLimit)
{
	Uint32 *pWDest;
	Uint8 *pSrc, *pDest;
	Uint8 *pChar;
	Uint8 i = 0;
	Uint8 j;
	Uint8 Len;
	Boolean Swap_Word;

	pChar = &pDhcpHdr->Options[4];
	while ((*pChar != DHCP_OP_ENDMARK) && (i < LenLimit)) {
		/* Search for the option */
		switch (pChar[0]) {
		case 0:
			/* Padding, skip it */
			i++;
			pChar++;
			continue;
		case DHCP_OP_LEASETIME:
			pDest = (Uint8 *) & pCB->LeaseTime;
			Swap_Word = TRUE;
			break;
		case DHCP_OP_SERVERID:
			pDest = (Uint8 *) & pCB->ServerID;
			Swap_Word = TRUE;
			break;
		case DHCP_OP_T1TIME:
			pDest = (Uint8 *) & pCB->T1Time;
			Swap_Word = TRUE;
			break;
		case DHCP_OP_T2TIME:
			pDest = (Uint8 *) & pCB->T2Time;
			Swap_Word = TRUE;
			break;
		default:
			/* We don't need these options */
			i += (pChar[1] + 2);
			pChar += (pChar[1] + 2);	/* Add Len to pChar to advance to next option */
			continue;
		}

		Len = pChar[1];
		pSrc = pChar + 2;
		for (j = 0; j < Len; j++) {
			pDest[j] = *pSrc++;
		}

		if (Swap_Word) {
			/* Need to swap words */
			pWDest = (Uint32 *) pDest;
			*pWDest = VALUE_NETORDu32 (pWDest[0]);
			/* *pWDest = SWAP_WORD(pWDest[0]); */
		}

		i += (pChar[1] + 2);
		pChar += Len + 2;		/* Add Len to pChar to advance to next option */
	}

	if (!pCB->LeaseTime || ((DHCP_MsgType == DHCP_OFFER) && !pCB->ServerID)) {
		/*
		 * Must have Lease time option in both OFFER and ACK and
		 * ServerID in OFFER.
		 */
		return (E_DHCP_CANT_ALLOC_MEM);
	}

	return (E_NONE);
}


/*
 * DHCP_TimerProc() is the timeout function for all DHCP timers. This function
 * is called by the kernel when a DHCP timer goes off. It executes all timer
 * types.
 */
Boolean
DHCP_TimerProc_ReplyMsg (void *parm1)
{
	DHCP_CB *pCB;
	Uint8 TimerType;
	DHCP_PKT *pHdr;
	Uint32 CurrTime;
	ExecMsg req_msg, new_retry_msg;
	ExecBuff req_buffer;
	ExecStatus status = ES_SUCCESS;
	struct udp_conn *udpc;
	DHCPPrivateData_t *dhcp_private = exec_get_my_data ();
	UdpTxMcastPktMsg *brcast_param;
	Uint32 Xid;
	Int32 indexl;

	Xid = (Uint32) parm1;

	for (indexl = 0; indexl < num_of_dhcp_pcb; indexl++) {
		if (dhcp_array_cb[indexl].Xid == Xid)
			break;
	}

	if (indexl == num_of_dhcp_pcb) {
		DHCP_DEBUG ("DHCP_TimerProc_ReplyMsg: DID NOT FIND A MATCH\n");
		return FALSE;
	}

	pCB = &dhcp_array_cb[indexl];

	TimerType = (Uint8) pCB->TimerType;

	DHCP_DEBUG ("DHCP_TimerProc_ReplyMsg(): STATE %d; TimerType %d\n", pCB->State, pCB->TimerType);

	switch (TimerType) {
	case DHCP_MSG_WAIT4REPLY_TIMEOUT:
		if ((pCB->State != DHCP_STATE_SELECT) &&
			(pCB->State != DHCP_STATE_REQ) &&
			(pCB->State != DHCP_STATE_RENEW) && (pCB->State != DHCP_STATE_REBIND)) {

			DHCP_DEBUG ("%s<%d>:  DHCP_MSG_WAIT4REPLY_TIMEOUT Bad State!\n", __FILE__, __LINE__);
			pCB->DhcpWait4ReplyMsg = NULL;

			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
						STRING_NUM (dhcp_proxy_illegal_state));

			return (FALSE);
		}

		if (pCB->Retry >= dhcp_private->client_max_retry) {
			/* Has reached max retransmission */
			/* Free the saved buffer */

			DHCP_DEBUG ("HiperClient%d reached DHCP_MAX_RETRY \n", pCB->dhcp_connection_id);
			if (pCB->SavedpBD != NULL) {
				exec_free_bchain (pCB->SavedpBD, DEFAULT_FLAGS);
				pCB->SavedpBD = NULL;
				DHCP_DEBUG ("MAX RETRANS DONE Free the Saved buffer\n");
			}

			if (pCB->State == DHCP_STATE_RENEW) {
				/*Failed to get an ACK from the T1 request, start T2 timer */

				pCB->TimerType = DHCP_MSG_LEASET2UP_TIMEOUT;

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

				DHCP_DEBUG
					("DHCP_TimerProc_ReplyMsg(): DHCP_STATE_RENEW - T1 ACK failed Starting T2 timer.\n");
				pCB->DhcpWait4ReplyMsg = new_retry_msg;
				return (FALSE);	/* stop the DHCP_STATE_RENEW retry alarm */
			} else if (pCB->State == DHCP_STATE_REBIND) {
				/* Failed to get an ACK from T2 request, start Lease timer */

				if (pCB->DhcpWait4ReplyMsg == NULL)	/* If stopped by del_ip */
					return (FALSE);

				pCB->DhcpWait4ReplyMsg = NULL;

				pCB->TimerType = DHCP_MSG_LEASEUP_TIMEOUT;

				DHCP_DEBUG ("DHCP_fsm(): Starting DHCP_MSG_LEASEUP_TIMEOUT in state %d\n", pCB->State);
				new_retry_msg =
					exec_set_alarm (DHCP_TimerProc_ReplyMsg, (void *) pCB->Xid,
									MAGIC_NUMBER ('D', 'P', 'T', 'P'),
									pCB->LeaseTime - (pCB->T2Time +
													  DHCP_WAIT4REPLY_TIMEOUT * DHCP_MAX_RETRY),
									TMRF_SECONDS, &status);
				if (status != ES_SUCCESS) {
					pCB->DhcpWait4ReplyMsg = NULL;
					DHCP_Release ((DHCP_CB *) pCB);
					exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_CRITICAL,
								DHCP_STRINGS, STRING_NUM (dhcp_fail_set_timer), status);

					return (FALSE);	/* Tell RoboExec to stop alarm */
				}
				DHCP_DEBUG
					("DHCP_TimerProc_ReplyMsg(): DHCP_STATE_REBIND - T2 ACK failed Starting lease end timer.\n");
				pCB->DhcpWait4ReplyMsg = new_retry_msg;
				return (FALSE);	/* stop the DHCP_STATE_REBIND retry alarm */
			} else {
				/*
				 * Has either sent a DISCOVER or first REQUEST
				 * and received no reply from DHCP server,
				 * give up: free pCB
				 */

				DHCP_DEBUG
					("DHCP_TimerProc_ReplyMsg(): No reply recd. for DISCOVER/REQ max retransmission over.\n");

				pCB->DhcpWait4ReplyMsg = NULL;
				DHCP_Release ((DHCP_CB *) pCB);

				return (FALSE);
			}
		}

		/* Retransmission */
		pCB->Retry++;
		DHCP_DEBUG ("Retry %d for HiperClient%d\n", pCB->Retry, pCB->dhcp_connection_id);

		/* prepare broadcast UDP message for RETRY */
		req_msg = exec_alloc_msg (sizeof (UdpTxMcastPktMsg),
								  UDP_MCAST_SEND_REQ, DEFAULT_FLAGS, &status);
		if (req_msg == NULL || status != ES_SUCCESS) {
			pCB->DhcpWait4ReplyMsg = NULL;
			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 (FALSE);		/* Stop the timer also */
		}

		if (pCB->SavedpBD == NULL) {
			/* There should be something to retransmit */
			pCB->DhcpWait4ReplyMsg = NULL;
			exec_freemsg (req_msg, DEFAULT_FLAGS);
			DHCP_DEBUG ("There is no buffer to retransmit.\n");
			return (FALSE);
		} else {
			req_buffer = exec_duplicate_bchain (pCB->SavedpBD, DEFAULT_FLAGS, &status);
			if ((req_buffer == NULL) || (status != ES_SUCCESS)) {
				exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
							STRING_NUM (dhcp_error_dup_bchain), __FILE__, __LINE__, status);
				exec_free_bchain (pCB->SavedpBD, DEFAULT_FLAGS);
				exec_freemsg (req_msg, DEFAULT_FLAGS);
				return (FALSE);
			}
		}

		pHdr = (DHCP_PKT *) (BUFFER_PTR (req_buffer));

		CurrTime = exec_get_clock ();
		pHdr->ElapsedSec = CurrTime - (pCB->InitTime);

		memset (&pHdr->ClientHwAddr, 0, CLIENT_HW_ADDR_LEN);
		COPY_MAC_ADDR (&pHdr->ClientHwAddr, &my_mac_addr);

		brcast_param = (UdpTxMcastPktMsg *) EXEC_GET_MSG_PARAM (req_msg);
		udpc = &brcast_param->udpc;

		/* Initialise the connection block */
		udp_conn_init (udpc);

		DHCP_DEBUG ("DHCP: Sending discover/request in DHCP_MSG_WAIT4REPLY_TIMEOUT to %ai\n",
					&pCB->DestIpAddr);

		/* Set source and destination UDP ports */
		udp_conn_set_dst (udpc, VALUE_NETORDu16 (BOOTP_SERVER_PORT));
		udp_conn_set_src (udpc, VALUE_NETORDu16 (BOOTP_CLIENT_PORT));


		ip_conn_set_dst (udp_conn_get_ip_conn (udpc), pCB->DestIpAddr);
		ip_conn_set_src (udp_conn_get_ip_conn (udpc), SrcIpAddr);

		EXEC_SET_MSG_BUFFER (req_msg, req_buffer);

		status = exec_sendmsg (req_msg, pCB->udp_mbox, DEFAULT_FLAGS);

		if (status != ES_SUCCESS) {
			exec_Event (PEVT_DHCP, EVT_ALLSINKS,
						EVL_UNUSUAL, DHCP_STRINGS, STRING_NUM (dhcp_fail_passing), status);
			exec_freemsg (req_msg, DEFAULT_FLAGS);
			pCB->DhcpWait4ReplyMsg = NULL;
			return (FALSE);
		}

		/* return TRUE, ROBOEXEC will reactivate timer. */
		return (TRUE);

		break;

	case DHCP_MSG_LEASET1UP_TIMEOUT:
		/* Send out a DHCP_REQUEST to renew the IP addr. lease */
		DHCP_DEBUG ("DHCP_TimerProc_ReplyMsg(): DHCP_MSG_LEASET1UP_TIMEOUT \n");
		if (pCB->State != DHCP_STATE_BOUND) {
			exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL,
						DHCP_STRINGS, STRING_NUM (dhcp_proxy_illegal_state));
			pCB->DhcpWait4ReplyMsg = NULL;
			return (FALSE);
		}
		pCB->DhcpWait4ReplyMsg = NULL;
		pCB->State = DHCP_STATE_BOUND_T1;
		/* Call the DHCP state machine */
		DHCP_fsm (pCB, NULL, NULL, (Uint8) 0, dhcp_private);

		break;

	case DHCP_MSG_LEASET2UP_TIMEOUT:
		/* Send out a broadcast DHCP_REQUEST to renew the IP addr. lease */
		DHCP_DEBUG ("DHCP_TimerProc_ReplyMsg(): DHCP_MSG_LEASET2UP_TIMEOUT \n");
		if (pCB->State != DHCP_STATE_RENEW) {
			exec_Event (PEVT_DHCP, EVT_ALLSINKS,
						EVL_UNUSUAL, DHCP_STRINGS, STRING_NUM (dhcp_proxy_illegal_state));

⌨️ 快捷键说明

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