📄 dhcp_proxy.c
字号:
param = (DhcpIPReqMsg *) EXEC_GET_MSG_PARAM (pCB->msg);
SETu32 (¶m->framed_ip_address, 0);
DHCP_DEBUG ("DHCP_freeCB(): Respond to IP with %ai\n", ¶m->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 + -