📄 dhcp_client.c
字号:
/******************************************************************************\
Copyright (c) 2007, UTStarcom,Inc. (ShenZhen R&D Center)
All Rights Reserved.
Subsystem : WIMAX
Group : GW/AnchorEP/DHCP
File : dhcp_client.c
Version :
Build :
Author : kevin.shi
Maintained by : kevin.shi
Create Date : 2007-01-01
Last Modify :
Description : DHCP clients sim
\******************************************************************************/
/*
-----------------------------------------------------------
Software Develop CodeName :
Module Reference :
-----------------------------------------------------------
Change History:
07-01.01 kevin.shi create file.
*/
/* includes */
#include <stdio.h>
#include <stdlib.h>
#include <ioLib.h>
#include <socket.h>
#include <sockLib.h>
#include <inetLib.h>
#include <in.h>
#include <intLib.h>
#include "vxWorks.h"
#include "net/mbuf.h"
#include "net/protosw.h"
#include "sys/socket.h"
#include "net/socketvar.h"
#include "errno.h"
#include "net/if.h"
#include "net/route.h"
#include "netinet/in.h"
#include "netinet/in_pcb.h"
#include "netinet/in_systm.h"
#include "netinet/ip.h"
#include "netinet/in_var.h"
#include "netinet/ip_var.h"
#include "netinet/ip_icmp.h"
#include "netinet/udp.h"
#include "netinet/udp_var.h"
#include "net/systm.h"
#include "global.h"
#include "bs_common.h"
#include "dhcp_client.h"
#include "dhcp.h"
#include "dhcp_comm.h"
#include "gw_up_if.h"
#define DHCP_CLIENT_BINDING_MAX_NUM 2048
#define DHCP_CLIENT_RESOURCE_MAX_NUM DHCP_CLIENT_BINDING_MAX_NUM
#define DHCP_CLIENT_MSGQ_MSG_LEN 2048
#define DHCP_CLIENT_MSGQ_MSG_NUM 600
#define DHCP_CLIENT_TASK_PRIORITY 100
#define DHCP_CLIENT_TASK_STACK_SIZE 0x10000
#define DHCP_CLIENT_CID_HASH_LEN 1024
#define DHCP_CLIENT_HADDR_HASH_LEN DHCP_CLIENT_CID_HASH_LEN
/* DHCP client states */
#define INIT 0
#define WAIT_OFFER 1
#define SELECTING 2
#define REQUESTING 3
#define BOUND 4
#define RENEWING 5
#define REBINDING 6
#define INIT_REBOOT 7
/*#define VERIFY 8*/
#define REBOOTING 9
#define VERIFYING 10
#define INFORMING 11
#define RENEW_RETRY 12
#define REBIND_RETRY 13
#define MAX_STATES REBIND_RETRY + 1
#define MAX_MBUF_PEND 256
typedef struct SysUdpStat
{
unsigned int sysUdpInput;
unsigned int sysUdpInputRaw;
unsigned int sysUdpInputRawDiscard;
unsigned int sysUdpInputHooker;
unsigned int sysUdpInputHookerDiscard;
unsigned int sysUdpInputHookerCopy;
unsigned int sysUdpInputHookerNonCopy;
unsigned int sysUdpInputHookerPullup;
unsigned int sysUdpInputHookerPullFail;
unsigned int sysUdpOutput;
unsigned int sysUdpOutputSegment;
unsigned int sysUdpOutputDiscard;
unsigned int sysUdpOutputCacheRoute;
unsigned int sysUdpOutputFailed;
unsigned int sysIpOutput;
}St_SysUdpStat;
St_SysUdpStat gSysUdpStat;
/* vendor suboptions for UTStarcom */
#define UTS_PAD 0
#define UTS_OPERATOR_DOMAIN 1
#define MAX_DOMAIN_LEN 64
struct dhcp_domain
{
int ref_cnt;
char name[MAX_DOMAIN_LEN];
};
typedef struct dhcp_client_global_config
{
int dhcpServerPort; /* server port */
int dhcpClientPort; /* client port */
int dhcpMaxMsgSize; /* max msg size */
unsigned int localIp;
unsigned int serverIp;
unsigned char domainName[DHCP_DOMAIN_NAME_MAX_LEN];
/* some test control */
unsigned char reqOrDiscover;
unsigned char discoverWithBroadcast;
unsigned char cidFlag;
unsigned char haddrFlag;
unsigned char reqListFlag;
struct vendor_class_id vendor_id;
struct user_class_id user_id;
struct dhcp_domain domain;
unsigned int subnet;
unsigned int reqLease;
unsigned short maxMsgSize;
unsigned int reqListLen;
unsigned char reqList[128];
}St_DhcpClientGlobalConfig;
St_DhcpClientGlobalConfig gDhcpClientGlobalConfig;
St_DhcpStat gDhcpClientStat;
St_DhcpRes gDhcpClientRes[DHCP_CLIENT_RESOURCE_MAX_NUM];
St_DhcpBinding gDhcpClientBinding[DHCP_CLIENT_BINDING_MAX_NUM];
St_DhcpBinding_List gDhcpClientBindFreeList;
St_DhcpBinding_List gDhcpClientBindCidList[DHCP_CLIENT_CID_HASH_LEN];
St_DhcpBinding_List gDhcpClientBindHaddrList[DHCP_CLIENT_HADDR_HASH_LEN];
int gDhcpClientTaskId;
int gDhcpTestTaskId;
MSG_Q_ID gDhcpClientMsgQId;
unsigned int rx_dhcpclentlen;
unsigned int gDhcpTestStop = 0;
GW_UP_DHCP_MSG gDhcpClientMsgOut; /* for out to dhcp server's msgQ as gw_up_dhcp_msg structure */
unsigned int gDhcpBroadcastIp = 0xffffffff;
struct msg dhcpcMsgIn; /* rx dhcp msg */
struct ip *pIpOut; /* point to gDhcpClientMsgOut.pktBuf[0] */
struct udphdr *pUdpOut;
struct dhcp *pDhcpcOut;
unsigned int gDhcpTestDelayTime;
unsigned int gDhcpTestNum;
St_DhcpBinding *gpDhcpClientTestBinding = NULL;
unsigned char dhcpCookie[] = RFC1048_MAGIC; /* DHCP message indicator. */
int gDhcpClientSubnet = 0;
int make_discover(St_DhcpBinding *pBinding);
int make_request(St_DhcpBinding * pBinding);
int make_decline(St_DhcpBinding * pBinding);
int make_release(St_DhcpBinding * pBinding);
extern unsigned char dhcpCookie[];
extern int get_cid (struct dhcp *, int, struct client_id *);
extern int get_haddr(struct dhcp *msg,struct chaddr *haddr);
extern int bindcidcmp(struct client_id * key, struct dhcp_binding *bp);
extern int bindhaddrcmp(struct chaddr *key, struct dhcp_binding *bp);
St_DhcpBinding* dhcp_client_alloc_binding();
int dhcp_client_free_binding(St_DhcpBinding *pBinding);
struct sockaddr_in gstAddrFrom;
struct sockaddr_in gstAddrTo;
char * gDhcpStateString[] = {
"NULL",
"ADFS_W4_INIT_DISCOVER",
"ADFS_W4_INIT_OFFER",
"ADFS_W4_INIT_REQUEST",
"ADFS_W4_INIT_ACK",
"ADFS_NORMAL",
"ADFS_W4_NORMAL_ACK",
NULL
};
char * gDhcpMsgString[] = {
"BOOTP",
"DHCPDISCOVER",
"DHCPOFFER",
"DHCPREQUEST",
"DHCPDECLINE",
"DHCPACK",
"DHCPNAK",
"DHCPRELEASE",
"DHCPINFORM",
NULL
};
char *gDhcpActingString[] = {
"NULL"
"Proxy",
"Proxy_Lap",
"Relay",
NULL
};
#ifdef BSSIM_BINDED_2_GW
extern MSG_Q_ID g_msgq_gwcp;
#define AEP_MSG_Q_ID g_msgq_gwcp
#else
#define AEP_MSG_Q_ID NULL
#endif
#if (defined(_DHCP_DEBUG_ ) && defined(_DHCP_USING_PRIV_DEBUG_))
unsigned int gDhcpTraceLevel;
unsigned int gDhcpDumpLevel;
#endif
#ifdef _DHCP_USING_PRIV_DEBUG_
void dhcp_breakpoint()
{
/* do nothing */
return;
}
unsigned int gDhcpAssertDebug = 0;
void Dhcp_Exception_Handle()
{
extern STATUS tt(int);
if (gDhcpAssertDebug) {
tt(0);
ti(0);
ts(0);
}
return ;
}
#endif
void CommUdpStat_Show(unsigned int clearFlag)
{
printf("UDP Stat :\n");
printf("sysUdpInput %8d\n",gSysUdpStat.sysUdpInput);
printf("sysUdpInputRaw %8d\n",gSysUdpStat.sysUdpInputRaw);
printf("sysUdpInputRawDiscard %8d\n",gSysUdpStat.sysUdpInputRawDiscard);
printf("sysUdpInputHooker %8d\n",gSysUdpStat.sysUdpInputHooker);
printf("sysUdpInputHookerDiscard %8d\n",gSysUdpStat.sysUdpInputHookerDiscard);
printf("sysUdpInputHookerCopy %8d\n",gSysUdpStat.sysUdpInputHookerCopy);
printf("sysUdpInputHookerNonCopy %8d\n",gSysUdpStat.sysUdpInputHookerNonCopy);
printf("sysUdpInputHookerPullup %8d\n",gSysUdpStat.sysUdpInputHookerPullup);
printf("sysUdpInputHookerPullFail %8d\n",gSysUdpStat.sysUdpInputHookerPullFail);
printf("\n");
printf("sysUdpOutput %8d\n",gSysUdpStat.sysUdpOutput);
printf("sysUdpOutputSegment %8d\n",gSysUdpStat.sysUdpOutputSegment);
printf("sysUdpOutputDiscard %8d\n",gSysUdpStat.sysUdpOutputDiscard);
printf("sysUdpOutputCacheRoute %8d\n",gSysUdpStat.sysUdpOutputCacheRoute);
printf("sysUdpOutputFailed %8d\n\n",gSysUdpStat.sysUdpOutputFailed);
printf("\n");
printf("sysIpOutput %8d\n",gSysUdpStat.sysIpOutput);
if (clearFlag) {
bzero((void *)&gSysUdpStat,sizeof(gSysUdpStat));
}
return ;
}
/* called by bsd_udp_output
support ip segmentation
*/
int
bsd_ip_output(struct mbuf *m0)
{
struct ip *ip, *mhip;
struct ifnet *ifp;
struct mbuf *m = m0;
struct sockaddr_in *dst;
struct in_ifaddr *ia;
int hlen = sizeof (struct ip);
int len, off, error = 0;
struct route *ro;
struct route iproute;
ip = mtod(m, struct ip *);
/*
* Fill in IP header.
*/
ip->ip_v = IPVERSION;
ip->ip_off &= IP_DF;
ip->ip_id = htons(ip_id++);
ip->ip_hl = hlen >> 2;
/*
* Route packet.
*/
ro = &iproute;
bzero((caddr_t)ro, sizeof (*ro));
dst = (struct sockaddr_in *)&ro->ro_dst;
dst->sin_family = AF_INET;
dst->sin_len = sizeof(*dst);
dst->sin_addr = ip->ip_dst;
TOS_SET (dst, ip->ip_tos);
/*
* If routing to interface only,
* short circuit routing lookup.
*/
#define ifatoia(ifa) ((struct in_ifaddr *)(ifa))
#define sintosa(sin) ((struct sockaddr *)(sin))
/*
* Ip route lookup
*/
rtalloc(ro);
if (0 == ro->ro_rt) {
ipstat.ips_noroute++;
error = EHOSTUNREACH;
goto bad;
}
ia = ifatoia(ro->ro_rt->rt_ifa);
ifp = ro->ro_rt->rt_ifp;
ro->ro_rt->rt_use++;
if (ro->ro_rt->rt_flags & RTF_GATEWAY)
dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
/*
* If source address not specified yet, use address
* of outgoing interface.
*/
if (ip->ip_src.s_addr == INADDR_ANY)
ip->ip_src = IA_SIN(ia)->sin_addr;
/*
* Look for broadcast address and
* and verify user is allowed to send
* such a packet.
*/
m->m_flags &= ~M_BCAST;
if (ifp->if_snd.ifq_len >= MAX_MBUF_PEND) {
error = ENOBUFS;
gSysUdpStat.sysUdpOutputDiscard++;
goto bad;
}
sendit:
/*
* If small enough for interface, can just send directly.
*/
if ((u_short)ip->ip_len <= ifp->if_mtu) {
ip->ip_len = htons((u_short)ip->ip_len);
ip->ip_off = htons((u_short)ip->ip_off);
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m, hlen);
error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst, ro->ro_rt);
gSysUdpStat.sysIpOutput++;
goto done;
}
gSysUdpStat.sysUdpOutputSegment++;
/*
* Too large for interface; fragment if possible.
* Must be able to put at least 8 bytes per fragment.
*/
if (ip->ip_off & IP_DF) {
error = EMSGSIZE;
ipstat.ips_cantfrag++;
goto bad;
}
len = (ifp->if_mtu - hlen) &~ 7;
if (len < 8) {
error = EMSGSIZE;
goto bad;
}
if (1) {
int mhlen, firstlen = len;
struct mbuf **mnext = &m->m_nextpkt;
/*
* Loop through length of segment after first fragment,
* make new header and copy data of each part and link onto chain.
*/
m0 = m;
mhlen = sizeof (struct ip);
for (off = hlen + len; off < (u_short)ip->ip_len; off += len) {
m = mHdrClGet(M_DONTWAIT, MT_HEADER, CL_SIZE_128, TRUE);
if (m == 0) {
error = ENOBUFS;
ipstat.ips_odropped++;
goto sendorfree;
}
m->m_flags = m0->m_flags;
m->m_data += max_linkhdr;
mhip = mtod(m, struct ip *);
*mhip = *ip;
if (hlen > sizeof (struct ip)) {
mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
mhip->ip_hl = mhlen >> 2;
}
m->m_len = mhlen;
mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
if (ip->ip_off & IP_MF)
mhip->ip_off |= IP_MF;
if (off + len >= (u_short)ip->ip_len)
len = (u_short)ip->ip_len - off;
else
mhip->ip_off |= IP_MF;
mhip->ip_len = htons((u_short)(len + mhlen));
m->m_next = m_copy(m0, off, len);
if (m->m_next == 0) {
(void) m_free(m);
error = ENOBUFS; /* ??? */
ipstat.ips_odropped++;
goto sendorfree;
}
m->m_pkthdr.len = mhlen + len;
m->m_pkthdr.rcvif = (struct ifnet *)0;
mhip->ip_off = htons((u_short)mhip->ip_off);
mhip->ip_sum = 0;
mhip->ip_sum = in_cksum(m, mhlen);
*mnext = m;
mnext = &m->m_nextpkt;
ipstat.ips_ofragments++;
}
/*
* Update first fragment by trimming what's been copied out
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -