static int dhcprequest(TP_PACKET_T *packet)
{
BOOL reqforme = FALSE;
struct dhcp_binding *res = NULL;
//struct dhcp_binding resCopy = {};
struct dhcp_binding *binding = NULL;
struct client_id cid;
DHCP_SERVER_IP reqip;
struct in_addr netmask;
unsigned long offer_lease = 0; /* offering lease */
unsigned long reqlease = 0; /* requested lease duration */
char *option = NULL;
int response; /* Accept request? */
BOOL hasReqip = FALSE; /* packet has REQUEST IP option */
DHCP_SERVER_IP networkIp; /* add by supeng 2011.3.8 */
char datestr[sizeof(EPOCH)];
char addrstr[sizeof(BRDCSTSTR)];
time_t curr_epoch = 0; /* current epoch */
struct chaddr tmpmac = {};
int ret = ERR_NO_ERROR;
struct in_addr poolNetworkIp;
struct in_addr poolNetmask;
int index = 0;
DHCP_SERVER_POOL pool_para={};
tmpmac.htype = dhcpsMsgIn.dhcp->htype;
tmpmac.hlen = dhcpsMsgIn.dhcp->hlen;
memcpy(tmpmac.haddr, dhcpsMsgIn.dhcp->chaddr, tmpmac.hlen);
memset((char *)&cid, 0, sizeof(cid));
memcpy(datestr, EPOCH, sizeof(EPOCH));
memcpy(addrstr, BRDCSTSTR, sizeof(BRDCSTSTR));
DEBUG_DHCPS("dhcprequst");
if (swDhcpsTime(&curr_epoch) != ERR_NO_ERROR)
{
DEBUG_DHCPS("Warning: Couldn't get timestamp when processing request.");
return (-1);
}
dhcpServerMutexTake();
response = 2;/* Response not determined. */
sendNak = 0;
reqlease = get_reqlease(dhcpsMsgIn.dhcp, priv_rdhcplen);
priv_maxoptlen = get_maxoptlen(dhcpsMsgIn.dhcp, priv_rdhcplen);
get_cid(dhcpsMsgIn.dhcp, priv_rdhcplen, &cid);
DBG_DHCP_VRF("cid is %s",bindCidtos(&cid,0,0));
if (get_subnet(dhcpsMsgIn.dhcp, priv_rdhcplen, cid.vrfName,&cid.subnet, packet) != 0)
{
DEBUG_DHCPS("requst:get subnet error.%x", cid.subnet.s_addr);
dhcpServerMutexGive();
return (-1);
}
DHCP_SERVER_POOL poolParam = {0};
DHCP_SERVER_IP cid_subnet_svr={};
COPY_SERVER_IP(cid_subnet_svr,cid.subnet,cid.vrfName);
/* 更新报文统计数 */
rtdDhcpsGetPoolByIp(cid_subnet_svr, &poolParam);
rtdDhcpServerChangePoolStatis(poolParam.name, DHCPREQUEST, 1);
DEBUG_DHCPS("requst:cid.subnet=%x",cid.subnet.s_addr);
/* Check if this DHCP server is the request destination.
(Option not present unless client is in SELECTING state). */
option = (char*)pickup_opt(dhcpsMsgIn.dhcp, priv_rdhcplen, _DHCP_SERVER_ID_TAG);
if (option != NULL)
{
if (swDhcpsIsServerIp(GETHL(OPTBODY(option))) == ERR_NO_ERROR)
{
reqforme = TRUE;
}
if (!reqforme)
{
DEBUG_DHCPS("requst: not request for this SERVER!");
dhcpServerMutexGive();
return (-1);
}
}
/* 获取入口vlan的网段信息 */
swDhcpsGetNetworkMaskByVid(packet->vid, &networkIp.ip, &netmask);
COPY_VRF(networkIp.vrfName,cid.vrfName);
/* Requesting client has no IP address (i.e. - initial request
* from SELECTING state or verification of cached lease from
* INIT-REBOOT state).*/
/* 获取请求ip */
reqip.ip.s_addr = 0;
option = (char*)pickup_opt(dhcpsMsgIn.dhcp, priv_rdhcplen, _DHCP_REQUEST_IPADDR_TAG);
if (option != NULL)
{
reqip.ip.s_addr = (GETHL(OPTBODY(option)));
COPY_VRF(reqip.vrfName,cid.vrfName);
hasReqip = TRUE;
}
DBG_DHCP_VRF("reqip=%s", inet_ntoa(reqip.ip));
/* first deal with manual binding */
struct dhcp_binding tmpBp;
memset(&tmpBp, 0, sizeof(tmpBp));
/* 静态绑定地址,cid优先 */
ret = rtdDhcpServerGetBindEntryByCid(&cid, bindcidcmp_manual,&tmpBp);
if (ret == ERR_NO_ERROR && tmpBp.cid.idtype != ETHERNET_BIND && tmpBp.cid.idtype != IEEE802_BIND)
{
binding = &tmpBp;
}
/* 静态绑定条目,无需判断时间戳---chenwenjing 2015.5.21 */
if (binding != NULL && binding->flag >= TEMP_ENTRY )
{
DEBUG_DHCPS("dhcp munual binding for cid found");
res = binding;
if (hasReqip)
{
DEBUG_DHCPS("manual-binding: with Request Ip option");
DBG_DHCP_MLAG("res->ip_addr.s_addr: %x dhcpsMsgIn.dhcp->ciaddr.s_addr: %x", res->ip_addr.ip.s_addr, dhcpsMsgIn.dhcp->ciaddr.s_addr);
DBG_DHCP_MLAG("res->ip_addr: %s, reqip: %s", inet_ntoa(res->ip_addr.ip), inet_ntoa(reqip.ip));
//if (res->ip_addr.ip.s_addr == reqip.s_addr&&DHCP_VRF_NAME_SAME(cid.vrfName,res->cid.vrfName))
if(DHCP_SERVER_IP_SAME(res->ip_addr,reqip))///???报错
{
ret = dhcpServerChkReqIpAvailable(reqip, networkIp, packet, NULL);
if (ret == TRUE)
{
response = 1;
}
}
else
{
response = 0;
sendNak = 1;
}
}
else
{
DEBUG_DHCPS("res->ip_addr.s_addr: %s dhcpsMsgIn.dhcp->ciaddr.s_addr: %x", inet_ntoa(res->ip_addr.ip), inet_ntoa(dhcpsMsgIn.dhcp->ciaddr));
if (res->ip_addr.ip.s_addr == dhcpsMsgIn.dhcp->ciaddr.s_addr && (DHCP_VRF_NAME_SAME(res->ip_addr.vrfName,dhcpsMsgIn.vrfName)))
{
ret = dhcpServerChkReqIpAvailable(res->ip_addr, networkIp, packet, NULL);
if (ret == TRUE)
{
response = 1;
}
}
}
}
/* 静态绑定,haddr */
if (response == 2)
{
struct client_id tmpCid;
memset(&tmpCid, 0, sizeof(tmpCid));
tmpCid.idtype = cid.idtype;
tmpCid.idlen = tmpmac.hlen;
tmpCid.subnet=cid.subnet;
memcpy(tmpCid.id, tmpmac.haddr, tmpmac.hlen);
COPY_VRF(tmpCid.vrfName,cid.vrfName);
ret = rtdDhcpServerGetBindEntryByCid(&tmpCid, bindcidcmp_manual, &tmpBp);
if (ret == ERR_NO_ERROR)
{
binding = &tmpBp;
}
else
{
binding = NULL;
}
/* 静态绑定条目,无需判断时间戳---chenwenjing 2015.5.21 */
if (binding != NULL && binding->flag >= TEMP_ENTRY)
{
DEBUG_DHCPS("temp_epoch:%d, curr_epoch:%d", (int)binding->temp_epoch, (int)curr_epoch);
DEBUG_DHCPS("dhcp binding for haddr found");
res = binding;
if (hasReqip)
{
DEBUG_DHCPS("manual-binding: with Request Ip option");
if(DHCP_SERVER_IP_SAME(res->ip_addr,reqip))
{
ret = dhcpServerChkReqIpAvailable(reqip, networkIp, packet, NULL);
if (ret == TRUE)
{
response = 1;
}
}
else
{
response = 0;
sendNak = 1;
}
}
else
{
if (res->ip_addr.ip.s_addr == dhcpsMsgIn.dhcp->ciaddr.s_addr && (DHCP_VRF_NAME_SAME(res->ip_addr.vrfName,dhcpsMsgIn.vrfName)))
{
ret = dhcpServerChkReqIpAvailable(res->ip_addr, networkIp, packet, NULL);
if (ret == TRUE)
{
response = 1;
}
}
}
}
}
/* 曾经分配给客户端的IP地址信息 */
if (response == 2)
{
ret = rtdDhcpServerGetBindEntryByCid(&cid, bindcidcmp_not_manual, &tmpBp);//为啥没在这里找到?
if (ret == ERR_NO_ERROR)
{
binding = &tmpBp;
}
else
{
binding = NULL;
}
if (binding != NULL && binding->flag >= TEMP_ENTRY && binding->temp_epoch > curr_epoch)
{
DEBUG_DHCPS("dhcp binding for cid found");
res = binding;
if (hasReqip)
{
DEBUG_DHCPS("auto-binding: with Request Ip option");
DBG_DHCP_MLAG("res->ip_addr: %u, reqip: %u",res->ip_addr.ip.s_addr,reqip.ip.s_addr);
DBG_DHCP_MLAG("res->ip_addr: %s, reqip: %s", inet_ntoa(res->ip_addr.ip), inet_ntoa(reqip.ip));
DBG_DHCP_MLAG("res->ip_addr: %u, reqip: %u",res->ip_addr.ip.s_addr,reqip.ip.s_addr);
//if (res->ip_addr.s_addr == reqip.s_addr)
if(DHCP_SERVER_IP_SAME(res->ip_addr,reqip))
{
ret = dhcpServerChkReqIpAvailable(reqip, networkIp, packet, NULL);
if (ret == TRUE)
{
response = 1;
}
}
else
{
DBG_DHCP_MLAG("");
response = 0;
sendNak = 1;
}
}
else
{
DEBUG_DHCPS("res->ip_addr.s_addr: %x dhcpsMsgIn.dhcp->ciaddr.s_addr: %x", res->ip_addr.ip.s_addr, dhcpsMsgIn.dhcp->ciaddr.s_addr);
if (res->ip_addr.ip.s_addr == dhcpsMsgIn.dhcp->ciaddr.s_addr && (DHCP_VRF_NAME_SAME(res->ip_addr.vrfName,dhcpsMsgIn.vrfName)))
{
ret = dhcpServerChkReqIpAvailable(res->ip_addr, networkIp, packet, NULL);
if (ret == TRUE)
{
response = 1;
}
}
}
}
}
int needNak = 0;
/* 通过request ip */
if (response == 2 && hasReqip) /* Response still undetermined. */
{
if (reqip.ip.s_addr != 0)
{
binding = NULL;
ret = rtdDhcpServerGetBindEntryByIp(reqip, &tmpBp);
if (ret == ERR_NO_ERROR)
{
res = &tmpBp;
DEBUG_DHCPS("select_wreqip:res!=null");
rtdDhcpsPoolGetNetworkAndMask(res->poolName, &poolNetworkIp, &poolNetmask);
rtdDhcpsGetPoolByPoolName(res->poolName,&pool_para);
if (poolNetworkIp.s_addr == (res->ip_addr.ip.s_addr & poolNetmask.s_addr)
&& DHCP_VRF_NAME_SAME(pool_para.vrfName,cid.vrfName)
&& res->flag >= TEMP_ENTRY
&& res->temp_epoch >= curr_epoch
&& (cid.subnet.s_addr == (res->ip_addr.ip.s_addr & poolNetmask.s_addr))
&& ((memcmp(res->haddr.haddr, tmpmac.haddr, tmpmac.hlen) == 0
&& res->haddr.htype == tmpmac.htype)
|| (memcmp(res->cid.id, cid.id, cid.idlen) == 0)))
{
binding = &tmpBp;
}
}
if (binding != NULL)
{
needNak =0;
ret = dhcpServerChkReqIpAvailable(reqip, networkIp, packet, &needNak);
if (ret == TRUE)
{
DBG("reponse=1");
response = 1;
}
else if (needNak == 1)
{
response = 0;
sendNak = 1;
}
}
}
}
/* 通过ciaddr, 原来已获取的ip---特指续约状态下 */
if (response == 2 && !hasReqip) /* Response still undetermined. */
{
//reqip.s_addr = dhcpsMsgIn.dhcp->ciaddr.s_addr;
COPY_SERVER_IP(reqip,dhcpsMsgIn.dhcp->ciaddr,dhcpsMsgIn.vrfName);
if (reqip.ip.s_addr != 0)
{
binding = NULL;
ret = rtdDhcpServerGetBindEntryByIp(reqip, &tmpBp);
if (ret == ERR_NO_ERROR)
{
res = &tmpBp;
DEBUG_DHCPS("select_wreqip:res!=null");
rtdDhcpsPoolGetNetworkAndMask(res->poolName, &poolNetworkIp, &poolNetmask);
if (poolNetworkIp.s_addr == (res->ip_addr.ip.s_addr & poolNetmask.s_addr)
&& res->flag >= TEMP_ENTRY
&& res->temp_epoch >= curr_epoch
&& (cid.subnet.s_addr == (res->ip_addr.ip.s_addr & poolNetmask.s_addr))
&& ((memcmp(res->haddr.haddr, tmpmac.haddr, tmpmac.hlen) == 0
&& res->haddr.htype == tmpmac.htype)
|| (memcmp(res->cid.id, cid.id, cid.idlen) == 0)))
{
binding = &tmpBp;
}
}
if (binding != NULL)
{
needNak =0;
ret = dhcpServerChkReqIpAvailable(reqip, networkIp, packet, &needNak);
if (ret == TRUE)
{
response = 1;
}
else if (needNak == 1)
{
response = 0;
sendNak = 1;
}
}
}
}
/* Ignore message if needed IP address not present. */
/*
* Client's notion of IP address is incorrect -
* deny the request. (Follows suggested behavior
* of RFC 1541 for client in SELECTING state).
*/
if (response == 2) /* Don't exit if response undetermined. */
{
if (dhcpsMsgIn.dhcp->giaddr.s_addr != 0)
{
DEBUG_DHCPS("send nak:giaddr=%s,reqip=%s,netmask=%s",
inet_ntoa(dhcpsMsgIn.dhcp->giaddr),inet_ntoa(reqip.ip),inet_netof(netmask));
}
else
{
DEBUG_DHCPS("send nak:addrpool=%s,req_ip=%s,netmask=%s",
inet_ntoa(networkIp.ip),inet_ntoa(reqip.ip),inet_ntoa(netmask));
}
response = 0; /* Send NAK to client. */
}
if (response == 1 && swDhcpsIpIsEnable(binding->ip_addr) != OK && res->expire_epoch != DHCP_SERVER_FORERVER)//ip是动态绑定的,却存在手动绑定条目,则认为出错
{
DEBUG_DHCPS("ip is not enable");
response = 0;
sendNak = 1;
}
if (response == 1) /* A DHCP server will send ACK to client. */
{
DEBUG_DHCPS("ack");
#ifdef PFM_TO_DO
#ifdef INC_DHCPSNOOP
if (swDhcpSnoopChkEntryIsReachLimit(packet, res->ip_addr.s_addr))
{
if (dhcpsMsgIn.dhcp->ciaddr.s_addr != 0)
{
if (res)
{
if (res->flag > TEMP_ENTRY)
{
dhcpsSendRuntimeData(DHCPS_BIND_DEL, res);
}
res->flag = FREE_ENTRY;
}
construct_msg(DHCPNAK, NULL, offer_lease, packet);
if (0 == send_dhcp(packet, DHCPNAK))
{
if (reqip.s_addr != 0)
{
dhcpServerSendReplyMsgToMainQueue(DHCPNAK, htonl(reqip.s_addr),
(UINT8 *)dhcpsMsgIn.dhcp->chaddr, 0, htonl(dhcpsMsgIn.dhcp->xid));
}
}
}
dhcpServerMutexGive();
return -1;
}
#endif
#endif
offer_lease = choose_lease(reqlease, curr_epoch, res);//更新租约时长
DBG("lease is %d",offer_lease);
if (rtdDhcpServerUpdateEntryByIp(DHCPREQUEST, res->ip_addr, offer_lease, curr_epoch, BIND_ENTRY) != 0)
{
if (reqforme == TRUE) /* Error in selected server's database. */
{
response = 0;
}
else
{
DEBUG_DHCPS("update_db error");
dhcpServerMutexGive();
return (-1);
}
}
if (response == 1) /* Lease selected and stored in database. */
{
DHCP_SERVER_RUNTIME_MSG runTimeMsg;
int oldFlg = 0;
oldFlg = res->flag;
res->flag = BIND_ENTRY;
DEBUG_DHCPS("ack construct_msg");
if (offer_lease == DHCP_SERVER_FORERVER)
{
res->expire_epoch = DHCP_SERVER_FORERVER;
}
else
{
res->expire_epoch = curr_epoch + offer_lease;
}
res->temp_epoch=res->expire_epoch;
construct_msg(DHCPACK, res, offer_lease, packet);
/* send DHCPACK from the interface
* xxx must be able to handle the fragments, but currently not
* implemented.
*/
if (0 == send_dhcp(packet, DHCPACK, res->poolName))
{
dhcpServerSendReplyMsgToMainQueue(DHCPACK, htonl(res->ip_addr.ip.s_addr),
(UINT8 *)dhcpsMsgIn.dhcp->chaddr, offer_lease, htonl(dhcpsMsgIn.dhcp->xid));
}
res->lease=offer_lease;
DBG_DHCP_MLAG("a binded entry formed: ");
_printBinding(*res);
memset(&runTimeMsg, 0, sizeof(DHCP_SERVER_RUNTIME_MSG));
memcpy(&runTimeMsg.binding, res, sizeof(struct dhcp_binding));
/* 如果是手动绑定条目或者是已经绑定的普通条目,都只需要更新?? */
if (MANUAL_BIND_TYPE == res->bindtype || oldFlg == BIND_ENTRY)
{
//#ifdef PFM_TODO
DBG("update rtd");
runTimeMsg.option = DHCPS_BIND_SET;
rtdDhcpsSendRuntimeData(&runTimeMsg);
//#endif
}
else
{
//#ifdef PFM_TODO
DBG("update rtd");
runTimeMsg.option = DHCPS_BIND_ADD;
rtdDhcpsSendRuntimeData(&runTimeMsg);
//#endif
}
dhcpServerMutexGive();
}
}
//只要没有处理成功,无论是否显式置nak,只要没有relay,都回复nak;有relay的情况下,只有当前面的处理后nak==1时才回复nak
if (response == 0) /* Deny request with NAK if client or server error occurred. */
{
DEBUG_DHCPS("sendnak: %d, dhcprGetGlobalStatus: %d", sendNak, dhcpRelayModuleGetGlobalStatus());
/* 如果Relay开启,尝试交给Relay处理,不发送NAK */
if (0 == sendNak && dhcpRelayModuleGetGlobalStatus())
{
DEBUG_DHCPS("dhcprToServer");
user_port up = {};
user_port rxUp = {};
UP_ITER_LIST(packet->uportList, index, up)
{
rxUp = up;
break;
}
ret = swDhcpsRelayToServer(packet->vid, rxUp, DHCPREQUEST,&dhcpsMsgIn);
if (ERR_NO_ERROR != ret)
{
DEBUG_DHCPS("DHCP relay error!!");
dhcpServerMutexGive();
return (-1);
}
dhcpServerMutexGive();
return (0);
}
DEBUG_DHCPS("send nak");
/* if request is for this server, reply with NAK. Otherwise
* throw the packet silently By huzhiyuan 2013,7,17
*/
//#ifdef PFM_TODO
if (res)
{
DHCP_SERVER_RUNTIME_MSG runTimeMsg;
memset(&runTimeMsg, 0, sizeof(DHCP_SERVER_RUNTIME_MSG));
memcpy(&runTimeMsg.binding, res, sizeof(struct dhcp_binding));
if (res->flag > 1)
{
DBG("update rtd");
runTimeMsg.option = DHCPS_BIND_DEL;
rtdDhcpsSendRuntimeData(&runTimeMsg);
}
res->flag = FREE_ENTRY;
}
//#endif
construct_msg(DHCPNAK, NULL, offer_lease, packet);
char poolName[DHCPS_POOLNAME_LEN + 1];
if (res)
{
memcpy(poolName, res->poolName, sizeof(res->poolName));
}
if (0 == send_dhcp(packet, DHCPNAK, poolName))
{
//发送nak成功
if (reqip.ip.s_addr != 0)
{
dhcpServerSendReplyMsgToMainQueue(DHCPNAK, htonl(reqip.ip.s_addr),
(UINT8 *)dhcpsMsgIn.dhcp->chaddr, 0, htonl(dhcpsMsgIn.dhcp->xid));
}
}
}
dhcpServerMutexGive();
return (0);
}对于这个函数 dhcp client renew发来的报文会怎么运行
最新发布