📄 dhcp_proxy.c
字号:
/* Send response back to IP with the IP address */
param = (DhcpIPReqMsg *) EXEC_GET_MSG_PARAM (pCB->msg);
COPY_NETORDu32 (¶m->framed_ip_address, &pCB->YourIpAddr);
DHCP_DEBUG ("dhcp_fsm(): Respond to IP with %ai\n", ¶m->framed_ip_address);
DHCP_DEBUG ("Responding to sender %s\n",
exec_get_process_name (EXEC_GET_MSG_SENDER (pCB->msg)));
exec_respond_to_msg (pCB->msg, IP_FWD_DHCP_IPADDR_RSP, ES_SUCCESS, DEFAULT_FLAGS);
dhcp_private->proxy_count.addr_acquired++;
pCB->ip_addr_acq = TRUE;
pCB->msg = NULL;
} else {
DHCP_DEBUG ("Address already acquired..Just Change the state to DHCP_STATE_BOUND.\n");
}
if (pCB->DhcpProxyIPMsg != NULL && pCB->ProxyTimerSet == TRUE) {
exec_stop_timer (pCB->DhcpProxyIPMsg, TMRF_CHECK_MBOX);
exec_freemsg (pCB->DhcpProxyIPMsg, DEFAULT_FLAGS);
DHCP_DEBUG ("got an ACK; setting pcb->ProxyIPMsg (%x, %x) to NULL\n", pCB,
pCB->DhcpProxyIPMsg);
pCB->DhcpProxyIPMsg = NULL;
pCB->ProxyTimerSet = FALSE;
}
if (pCB->LeaseTime != ~0UL) {
/* should be technically indefinite */
/* start lease renewal timer T1 */
pCB->T1Time = pCB->LeaseTime / 2; /* default */
pCB->T2Time = (pCB->LeaseTime / 4) * 3; /* default */
pCB->TimerType = DHCP_MSG_LEASET1UP_TIMEOUT;
DHCP_DEBUG ("DHCP_fsm(): Starting DHCP_MSG_LEASET1UP_TIMEOUT in state %d\n",
pCB->State);
pCB->DhcpWait4ReplyMsg =
exec_set_alarm (DHCP_TimerProc_ReplyMsg, (void *) pCB->Xid,
MAGIC_NUMBER ('D', 'P', 'T', 'I'), pCB->T1Time, TMRF_SECONDS,
&status);
if (status != ES_SUCCESS) {
DHCP_FreeCB ((DHCP_CB *) pCB);
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_CRITICAL,
DHCP_STRINGS, STRING_NUM (dhcp_fail_set_proxy_iptimer));
return;
}
} else {
pCB->T1Time = ~0UL;
pCB->T2Time = ~0UL;
}
return;
} else {
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_error_alloc_msg), status);
/*
* There might be something wrong with this IP addr.
* That's why the server NAKs it when we try to renew it.
* Don't use it, disconnect the NCP connection
*/
DHCP_DEBUG ("DHCP_fsm(): Got a NAK State = %d FreeCB\n", pCB->State);
DHCP_delete_ondemand (pCB);
DHCP_Release (pCB);
return;
}
break;
case DHCP_STATE_BOUND_T1:
DHCP_DEBUG ("DHCP_fsm(): DHCP_STATE_BOUND_T1 \n");
/* Called by DHCP_TimerProc(): Renewal time T1, send out a DHCP_REQUEST */
pCB->Retry = 1;
req_msg = exec_alloc_msg (sizeof (UdpSendMsg_t),
UDP_SEND_REQ, MSGF_CLEAR_PARAM | DEFAULT_FLAGS, &status);
if (req_msg == NULL || status != ES_SUCCESS) {
DHCP_FreeCB (pCB);
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_error_alloc_msg), status);
DHCP_DEBUG ("DHCP_SendReq(): dhcp_error_alloc_msg for req_msg, ERROR !\n");
return;
}
if ((RetCode = DHCP_SendReq (DHCP_REQUEST, pCB, NULL, pCB->ServerID,
FALSE, TRUE, req_msg, dhcp_private)) == E_NONE) {
dhcp_private->proxy_count.t1_renewals_sent++;
pCB->State = DHCP_STATE_RENEW;
} else {
/* Cannnot send request, free CB */
DHCP_DEBUG ("DHCP_fsm():DHCP_STATE_BOUND_T1 cannot send request FreeCB \n");
exec_freemsg (req_msg, DEFAULT_FLAGS);
DHCP_FreeCB (pCB);
return;
}
/* Start timer for retry */
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_BOUND_T2:
DHCP_DEBUG ("DHCP_fsm(): DHCP_STATE_BOUND_T2 \n");
/* Called by DHCP_TimerProc(): Renewal time T2,
send out a broadcast DHCP_REQUEST */
pCB->Retry = 1;
/* prepare broadcast UDP message for 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);
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_error_alloc_msg), status);
return;
}
if ((RetCode = DHCP_SendReq (DHCP_REQUEST, pCB, NULL, 0xffffffff,
FALSE, TRUE, req_msg, dhcp_private)) == E_NONE) {
dhcp_private->proxy_count.t2_renewals_sent++;
pCB->State = DHCP_STATE_REBIND;
} else {
/* Cannnot send request, free CB */
DHCP_DEBUG ("DHCP_fsm():DHCP_STATE_BOUND_T2 cannot send request FreeCB \n");
exec_freemsg (req_msg, DEFAULT_FLAGS);
DHCP_FreeCB (pCB);
return;
}
/* Start timer for retry */
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_BOUND_T2 */
case DHCP_STATE_BOUND:
DHCP_DEBUG ("DHCP_fsm():state DHCP_STATE_BOUND; got msg_type: %x Do Nothing\n", DHCP_MsgType);
break;
default:
DHCP_DEBUG ("DHCP_fsm():Invalid state %d (Default)\n", pCB->State);
DHCP_FreeCB (pCB);
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_proxy_fail_set_timer), status);
}
}
/*
* DHCP_SendReq() sends out a DHCP request whose type is specified in
* DHCP_CODE. It saves the pBD for retry later.
*/
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)
{
DHCP_PKT *pHdr;
Uint8 *pChar;
ExecBuff req_buffer;
UdpSendMsg_t *req_param;
UdpTxMcastPktMsg *brcast_param;
struct udp_conn *udpc;
ExecStatus status;
int offset;
/* check all flags ie. DhcpProxyEnabled, etc. */
if (!DHCPProxyEnabled) {
DHCP_DEBUG ("DHCP_proxy_req_proc(): DHCPProxy is not Enabled !\n");
return E_DHCP_SW_FAULT;
}
DHCP_DEBUG ("DHCP_SendReq(): DHCP_MsgType %d. Send MCAST | UCAST UDP packet\n", DHCP_MsgType);
/*
* Broadcast DHCP_REQUEST only if State != DHCP_STATE_BOUND_T1
*/
if ((DHCP_MsgType == DHCP_DISCOVER) ||
((DHCP_MsgType == DHCP_REQUEST) && (pCB->State != DHCP_STATE_BOUND_T1))) {
/* Broadcast UDP */
/* Point at the UDP connection block */
brcast_param = (UdpTxMcastPktMsg *) EXEC_GET_MSG_PARAM (req_msg);
udpc = &brcast_param->udpc;
} else {
req_param = (UdpSendMsg_t *) EXEC_GET_MSG_PARAM (req_msg);
req_param->bcst_flags = PF_NOT_BROADCAST;
udpc = &req_param->usc_udpc;
}
pCB->InitTime = exec_get_clock ();
pCB->Retry = 1;
DHCP_DEBUG ("The Xid for this transaction is = %u\n", pCB->Xid);
/* Grab a UDP packet buffer */
req_buffer = UDP_ALLOC (DHCP_MAX_PKT_SIZE, 0, status, MAGIC_NUMBER ('D', 'H', 'U', '0'));
if (status != ES_SUCCESS) {
return (E_DHCP_CANT_ALLOC_BUFFER);
}
/* UDP_ALLOC above doesn't clean it up ! */
memset (BUFFER_PTR (req_buffer), 0, DHCP_MAX_PKT_SIZE);
pHdr = (DHCP_PKT *) (BUFFER_PTR (req_buffer));
pHdr->OpCode = BOOTP_OP_CODE_REQUEST;
pHdr->HwType = HW_TYPE_ETHERNET;
pHdr->HwLen = HW_LEN_ETHERNET;
pHdr->Hops = 0;
COPY_NETORDu32 (&pHdr->Xid, &pCB->Xid);
pHdr->ElapsedSec = exec_get_clock () - (pCB->InitTime);
pHdr->ElapsedSec = VALUE_NETORDu16 (pHdr->ElapsedSec);
pHdr->Unused = 0x8000;
pHdr->ServerName[0] = '\0';
pHdr->FileName[0] = '\0';
SETu32 (&pHdr->GatewayIpAddr, 0);
if (DHCP_MsgType == DHCP_DISCOVER) {
/*
* Rightfully, in the DHCP Request, Ciaddr should also be set to 0 if
* there's no previous known IP addr, which is our case. If we set
* it to 0, the Incognito DHCP server will not use it to send out
* as the dest. IP addr in its DHCP AK, but the NT DHCP server will
* discard our DHCP Request. Since Incognito decides to fix its code,
* we'll just assign it to contain the newly offerred IP addr. to be
* interoperable with NT server even though this is not correct (refer
* to RFCs 951(Bootp server) and 1541 (DHCP server)).
*/
SETu32 (&pHdr->ClientIpAddr, 0);
} else {
/* ClientIpAddr set to offered Ip addr in REQUEST, DECLINE or RELEASE */
COPY_NETORDu32 (&pHdr->ClientIpAddr, &pCB->YourIpAddr);
}
SETu32 (&pHdr->YourIpAddr, 0);
SETu32 (&pHdr->ServerIpAddr, 0); /*For PRoxy clients set it to 0(temp) */
/*The 1st 4 bytes of the Option field (Vendor Info) is the magic cookie */
pChar = &pHdr->Options[0];
offset = 0;
SETu32 (pChar, MAGIC_COOKIE);
offset = 4;
ProxyAddSimpleOption (pHdr->Options, &offset, DHCP_OP_MSGTYPE, DHCP_MsgType);
ProxyAddULONGOption (pHdr->Options, &offset, DHCP_OP_LEASETIME, pCB->LeaseTime);
ProxyAddStringOption (pHdr->Options, &offset, DHCP_OP_CLIENT_HOSTNAME, pCB->ClientHostName);
ProxyAddMemOption (pHdr->Options, &offset, DHCP_OP_CLIENT_ID, pCB->ClientID, DHCP_MAX_CID_LEN);
/* Store the ServerID option */
if (StoreSrvrID) {
ProxyAddULONGOption (pHdr->Options, &offset, DHCP_OP_SERVERID, pCB->ServerID);
DHCP_DEBUG ("Storing ServerID %ai\n", &pCB->ServerID);
}
/* If this is a DHCP_REQ, put all options offered in DHCP_OFFER */
if (DHCP_MsgType == DHCP_REQUEST) {
COPY_NETORDu32 (&pHdr->ClientIpAddr, &pCB->YourIpAddr);
}
/*
* End Option
*/
pHdr->Options[offset] = DHCP_OP_ENDMARK;
/* Save Dest IP addr and BD for retransmission */
if (ReTx) {
COPY_NETORDu32 (&pCB->DestIpAddr, &DestIpAddr);
DHCP_DEBUG ("DHCP_SendReq(): ReTx, Duplicating pBD (pCB->SavedpBD).\n");
if (pBD == NULL) {
pCB->SavedpBD = exec_duplicate_bchain (req_buffer, DEFAULT_FLAGS, &status);
if ((pCB->SavedpBD == NULL) || (status != ES_SUCCESS)) {
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_error_dup_bchain), __FILE__, __LINE__, status);
return (E_DHCP_SW_FAULT);
}
} else {
pCB->SavedpBD = exec_duplicate_bchain (pBD, DEFAULT_FLAGS, &status);
if ((pCB->SavedpBD == NULL) || (status != ES_SUCCESS)) {
exec_free_bchain (pBD, DEFAULT_FLAGS);
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_error_dup_bchain), __FILE__, __LINE__, status);
return (E_DHCP_SW_FAULT);
}
} /* (pBD != NULL) */
}
memset (&pHdr->ClientHwAddr, 0, CLIENT_HW_ADDR_LEN);
COPY_MAC_ADDR (&pHdr->ClientHwAddr, &my_mac_addr);
/* Initialise the connection block */
udp_conn_init (udpc);
DHCP_DEBUG ("DHCP: Sending discover/request to %ai\n", &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), DestIpAddr);
ip_conn_set_src (udp_conn_get_ip_conn (udpc), SrcIpAddr);
/* Remember this function is never called with non NULL pBD... so its
** okey ...
*/
EXEC_SET_MSG_BUFFER (req_msg, req_buffer);
DHCP_DEBUG ("DHCP_SendReq(): calling udp_send_conn\n");
status = exec_sendmsg (req_msg, dhcp_private->udp_mbox, DEFAULT_FLAGS);
if (status != ES_SUCCESS) {
exec_Event (PEVT_DHCP, EVT_ALLSINKS,
EVL_UNUSUAL, DHCP_STRINGS, STRING_NUM (dhcp_error_udp_sendmsg), status);
DHCP_DEBUG ("DHCP_SendReq(): Cannot send msg to UDP\n");
return (E_DHCP_CANT_ALLOC_MEM);
}
/* Increment the counter */
if (DHCP_MsgType == DHCP_DISCOVER)
dhcp_private->proxy_count.discover_sent++;
return (E_NONE);
}
/*
* Release the IP and send call DHCP_Release when IP connection
* gets torn down
*
*/
void
DHCP_proxy_del_ip (ExecMsg msg)
{
DHCP_CB *pCB = &dhcp_array_cb[0];
Int32 i = 0;
Dhcp_DelIp *param;
param = EXEC_GET_MSG_PARAM (msg);
for (i = 0; i < num_of_dhcp_pcb; i++) {
if (pCB->YourIpAddr == param->intf_addr) {
DHCP_DEBUG ("DHCP_proxy_del_ip(): Found matching IP %ai\n", &pCB->YourIpAddr);
break;
}
pCB++;
}
if (i == num_of_dhcp_pcb) {
DHCP_DEBUG ("DHCP_proxy_del_ip() : DID NOT FIND A MATCH\n");
return;
}
DHCP_Release (pCB);
DHCP_DEBUG (" Free DHCP_DEL_IP msg \n");
exec_freemsg (msg, DEFAULT_FLAGS);
return;
}
/*
* DHCP_Release() sends a DHCP RELEASE request and frees the DHCP
* Control Block. Called by BCP and IPCP when they're taking
* down the NCP connection.
*/
void
DHCP_Release (DHCP_CB * pCB)
{
ExecStatus status = ES_SUCCESS;
DHCPPrivateData_t *dhcp_private = exec_get_my_data ();
DHCP_ERROR_CODE RetCode = E_NONE;
ExecMsg req_msg;
UdpSendMsg_t *req_param;
DHCP_DEBUG ("DHCP_Release(): Release IP and kill Timers \n");
req_msg = exec_alloc_msg (sizeof (UdpSendMsg_t),
UDP_SEND_REQ, MSGF_CLEAR_PARAM | DEFAULT_FLAGS, &status);
if (req_msg == NULL || status != ES_SUCCESS) {
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_error_alloc_msg), status);
DHCP_DEBUG ("DHCP_SendReq(): dhcp_error_alloc_msg for req_msg, ERROR !\n");
return;
}
req_param = (UdpSendMsg_t *) EXEC_GET_MSG_PARAM (req_msg);
req_param->bcst_flags = PF_NOT_BROADCAST;
req_param->policy.type = IP_POLICY_NONE;
DHCP_DEBUG ("DHCP_Release: pCB->ServerID = %ai\n", &pCB->ServerID);
if (pCB->ServerID != 0) {
/* We must have leased an IP addr. from a DHCP server, release it */
DHCP_DEBUG ("DHCP_Release: Send DHCP_RELEASE via udp \n");
if ((RetCode = DHCP_SendReq (DHCP_RELEASE, pCB, NULL, pCB->ServerID, TRUE, FALSE,
req_msg, dhcp_private)) != E_NONE)
exec_Event (PEVT_DHCP, EVT_ALLSINKS, EVL_UNUSUAL, DHCP_STRINGS,
STRING_NUM (dhcp_error_udp_sendmsg), status);
else
dhcp_private->proxy_count.released++;
} else {
/* No point in sending RELEASE, just free the message */
exec_freemsg (req_msg, DEFAULT_FLAGS);
}
/* Free the DHCP CB */
DHCP_FreeCB (pCB);
return;
}
/*
** This function will free up the pCB and rearrange the array so that
** ths deleted CB will be nulled
*/
void
DHCP_FreeCB (DHCP_CB * pCB)
{
Int32 indexl;
DhcpIPReqMsg *param;
for (indexl = 0; indexl < num_of_dhcp_pcb; indexl++) {
if (dhcp_array_cb[indexl].Xid == pCB->Xid)
break;
}
if (indexl == num_of_dhcp_pcb) {
DHCP_DEBUG ("DHCP_FreeCB: DID NOT FIND A MATCH\n");
return;
}
/* Kill timers */
if (pCB->DhcpWait4ReplyMsg != NULL) {
exec_stop_timer (pCB->DhcpWait4ReplyMsg, TMRF_CHECK_MBOX);
exec_freemsg (pCB->DhcpWait4ReplyMsg, DEFAULT_FLAGS);
pCB->DhcpWait4ReplyMsg = NULL;
}
if (pCB->DhcpProxyIPMsg != NULL && pCB->ProxyTimerSet == TRUE) {
exec_stop_timer (pCB->DhcpProxyIPMsg, TMRF_CHECK_MBOX);
exec_freemsg (pCB->DhcpProxyIPMsg, DEFAULT_FLAGS);
pCB->DhcpProxyIPMsg = NULL;
}
if (pCB->msg != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -