📄 dhcp_proxy.c
字号:
/*
* 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 + -