OCT 1. DHCP 服务支持自动识别VLAN、单层QinQ, 双层QinQ头部

This commit is contained in:
黄昕 2023-05-15 15:44:15 +08:00
parent a5d99d5dba
commit 958fbab193
5 changed files with 282 additions and 179 deletions

View File

@ -20,6 +20,12 @@ extern "C" {
#define VXLAN_VIN_ID_PACK(x) ((ntohs(x)) & 0xFFF)
typedef enum {
VLAN_NONE,
VLAN_LEVEL1,
VLAN_LEVEL2
} VLAN_TYPE;
typedef struct vlan_hdr {
#if VLAN_SUPPORT
U16 id;
@ -27,6 +33,21 @@ typedef struct vlan_hdr {
#endif
} VLAN_HDR, *PVLAN_HDR;
typedef struct vlan_hdr2 {
#if VLAN_SUPPORT
U16 id1;
U16 h_type;
U16 id2;
U16 type;
#endif
} VLAN_HDR2, *PVLAN_HDR2;
typedef struct {
struct ethhdr eth;
struct iphdr ip;
struct udphdr udp;
} VLAN_PKG_HDR, *PVLAN_PKG_HDR;
typedef struct {
struct ethhdr eth;
#if VLAN_SUPPORT
@ -34,7 +55,16 @@ typedef struct {
#endif
struct iphdr ip;
struct udphdr udp;
} VLAN_PKG_HDR, *PVLAN_PKG_HDR;
} VLAN_PKG_HDR1, *PVLAN_PKG_HDR1;
typedef struct {
struct ethhdr eth;
#if VLAN_SUPPORT
struct vlan_hdr2 vlan;
#endif
struct iphdr ip;
struct udphdr udp;
} VLAN_PKG_HDR2, *PVLAN_PKG_HDR2;
#pragma pack(pop)
#ifdef __cplusplus

View File

@ -114,7 +114,6 @@
#define LEASE_RELEASE_FMT "DELETE FROM lease WHERE uid = %d AND mac = '%s' AND ip = '%s'"
static int lease_add(PDHCP_REQ pReq,
const char *ip,
const char *netmask,
@ -400,10 +399,11 @@ int db_get_pre_lease(PDHCP_REQ pReq, PPOOL_CTX pAssign) {
const char *pIp = u32_to_str_ip_safe(htonl(pAssign->minAddr));
// 删除预分配IP信息
#if 0
memset(buf, 0, 2048);
sprintf(buf, "DELETE FROM pre_assign WHERE id = %llu;", id);
db_sqlite3_sql_exec(buf, NULL, NULL, NULL);
#endif
// 添加租约信息到lease数据库
lease_add(pReq, pIp, pNetmask, pGateway, pDns1, pDns2, pAssign->leaseTime);
@ -415,50 +415,6 @@ int db_get_pre_lease(PDHCP_REQ pReq, PPOOL_CTX pAssign) {
return ERR_SUCCESS;
}
return -ERR_ITEM_UNEXISTS;
#if 0
rc = db_sqlite3_get_rows(buf, &dbResult, &nRow, &nColumn, NULL);
if (rc == ERR_SUCCESS && nRow > 0 && nColumn > 0) {
char *pNetmask = dbResult[nColumn + 3];
char *pGateway = dbResult[nColumn + 4];
char *pDns1 = dbResult[nColumn + 5];
char *pDns2 = dbResult[nColumn + 6];
// minAddr 记录可分配的IP
pAssign->minAddr = ntohl(inet_addr(dbResult[nColumn + 1]));
pAssign->leaseTime = strtoul(dbResult[nColumn + 2], NULL, 10);
if (strlen(pNetmask) > 0) {
pAssign->netMask = ntohl(inet_addr(pNetmask));
}
if (strlen(pGateway) > 0) {
pAssign->gwAddr = ntohl(inet_addr(pGateway));
}
if (strlen(pDns1) > 0) {
pAssign->primeDNS = ntohl(inet_addr(pDns1));
}
if (strlen(pDns2) > 0) {
pAssign->salveDNS = ntohl(inet_addr(pDns2));
}
// 删除预分配IP信息
memset(buf, 0, 2048);
sprintf(buf, "DELETE FROM pre_assign WHERE id = %s;", dbResult[nColumn]);
//db_sqlite3_sql_exec(buf, NULL, NULL, NULL);
lease_add(pReq, dbResult[nColumn + 1], pNetmask, pGateway, pDns1, pDns2, pAssign->leaseTime);
sqlite3_free_table(dbResult);
return ERR_SUCCESS;
} else {
LOG_MOD(error, ZM_DHCP_DB, "No previously records: \n%s\n", buf);
}
sqlite3_free_table(dbResult);
return -ERR_ITEM_UNEXISTS;
#endif
}
int db_get_pre_assign(U32 uid, const char *mac, const char *hostname, U32 *preAssign) {

View File

@ -24,6 +24,10 @@
#define MAXIMUM_SNAPLEN (262144)
#define IP_HDR_OFFSET (sizeof(struct ethhdr))
#define UDP_HDR_OFFSET (sizeof(struct ethhdr) + sizeof(struct iphdr))
#define DHCP_OFFSET (sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr))
/*
TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are
responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT
@ -152,6 +156,18 @@ static NIC_INFO g_nicInfo;
static uv_udp_t g_uvRawSockReq;
static DHCP_WORK_MODE g_dhcpMode;
VLAN_TYPE get_package_vlan_type(void *pBuf) {
U8 *p = (U8 *)pBuf;
if (p[12] == 0x81 && p[13] == 0x00 && p[16] == 0x81 && p[17] == 0x00) {
return VLAN_LEVEL2;
} else if (p[12] == 0x81 && p[13] == 0x00) {
return VLAN_LEVEL1;
} else {
return VLAN_NONE;
}
}
U32 dhcp_get_default_netmask() {
return g_nicInfo.netmask;
}
@ -182,93 +198,172 @@ U32 pkg_mmap_tx(U8 *pData, U32 nBytes) {
return hdr->tp_len;
}
static void fill_package(PDHCP_PACKAGE pRsp, PDHCP_PACKAGE pReq) {
memset(pRsp, 0, MAX_DHCP_PKG_SIZE);
static void add_eth_head(U8 *pRsp, struct ethhdr *pEth, int isBst) {
struct ethhdr *p = (struct ethhdr *)pRsp;
// 二层头
// 目的IP地址
if (pReq->hdr.ip.saddr != 0) {
memcpy(pRsp->hdr.eth.h_dest, pRsp->hdr.eth.h_source, ETH_ALEN);
// 目的 MAC 地址
if (!isBst) {
memcpy(p->h_dest, pEth->h_source, ETH_ALEN);
} else {
memset(pRsp->hdr.eth.h_dest, 0xFF, ETH_ALEN);
memset(p->h_dest, 0xFF, ETH_ALEN);
}
// 源 IP 地址
memcpy(pRsp->hdr.eth.h_source, g_nicInfo.macAddr, ETH_ALEN);
// 源 MAC 地址
memcpy(p->h_source, g_nicInfo.macAddr, ETH_ALEN);
// protol
pRsp->hdr.eth.h_proto = pReq->hdr.eth.h_proto;
#if VLAN_SUPPORT
// QinQ 隧道
pRsp->hdr.vlan.id = pReq->hdr.vlan.id;
pRsp->hdr.vlan.type = pReq->hdr.vlan.type;
// TODO 可能的二层QinQ隧道
#endif
// IP 头
memcpy(&pRsp->hdr.ip, &pReq->hdr.ip, sizeof(struct iphdr));
// TOS
pRsp->hdr.ip.tos = 0;
// 更新源IP
pRsp->hdr.ip.saddr = g_nicInfo.ipAddr;
// 更新目的IP地址广播255.255.255.255
if (pReq->hdr.ip.saddr == 0) {
pRsp->hdr.ip.daddr = 0xFFFFFFFF;
} else {
pRsp->hdr.ip.daddr = pReq->hdr.ip.saddr;
p->h_proto = pEth->h_proto;
}
static void add_vlan_head(U8 *pRsp, PVLAN_PKG_HDR1 pvHdr) {
PVLAN_PKG_HDR1 p = (PVLAN_PKG_HDR1)pRsp;
// QinQ 隧道
p->vlan.id = pvHdr->vlan.id;
p->vlan.type = pvHdr->vlan.type;
}
static void add_vlan2_head(U8 *pRsp, PVLAN_PKG_HDR2 pvHdr) {
PVLAN_PKG_HDR2 p = (PVLAN_PKG_HDR2)pRsp;
// QinQ 隧道
p->vlan.id1 = pvHdr->vlan.id1;
p->vlan.h_type = pvHdr->vlan.h_type;
p->vlan.id2 = pvHdr->vlan.id2;
p->vlan.type = pvHdr->vlan.type;
}
static void add_ip_head(struct iphdr *p, struct iphdr *pIp) {
// IP 头
memcpy(p, pIp, sizeof(struct iphdr));
// TOS
p->tos = 0;
// 更新源IP
p->saddr = g_nicInfo.ipAddr;
// 更新目的IP地址广播255.255.255.255
if (pIp->saddr == 0) {
p->daddr = 0xFFFFFFFF;
} else {
p->daddr = pIp->saddr;
}
}
static void add_udp_head(struct udphdr *p, struct udphdr *pUdp) {
// UDP 头
// 目的端口
pRsp->hdr.udp.dest = pReq->hdr.udp.source;
p->dest = pUdp->source;
// 源端口
pRsp->hdr.udp.source = pReq->hdr.udp.dest;
p->source = pUdp->dest;
}
static void add_dhcp_common(PDHCP_PROTO p, PDHCP_PROTO pDhcp) {
//DHCP 协议
// 返回类型
pRsp->dhcp.op = BOOTP_REPLY;
p->op = BOOTP_REPLY;
// 地址类型长度
pRsp->dhcp.htype = pReq->dhcp.htype;
p->htype = pDhcp->htype;
// 地址长度
pRsp->dhcp.hlen = pReq->dhcp.hlen;
p->hlen = pDhcp->hlen;
// xid
pRsp->dhcp.xid = pReq->dhcp.xid;
p->xid = pDhcp->xid;
// 客户端 MAC 地址
memcpy(pRsp->dhcp.chaddr, pReq->dhcp.chaddr, ETH_ALEN);
memcpy(p->chaddr, pDhcp->chaddr, ETH_ALEN);
// DHCP服务端主机名
memcpy(pRsp->dhcp.sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname)));
memcpy(p->sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname)));
// Magic Cookie: DHCP
//
// memcpy(&pRsp->dhcp.cookie, DHCP_COOKIE_VAL, 4);
pRsp->dhcp.cookie = htonl(DHCP_COOKIE_VAL);
p->cookie = htonl(DHCP_COOKIE_VAL);
pRsp->dhcp.hops = 0;
pRsp->dhcp.secs = 0;
pRsp->dhcp.flags = 0;
pRsp->dhcp.ciaddr = 0;
pRsp->dhcp.siaddr = 0;
pRsp->dhcp.giaddr = 0;
p->hops = 0;
p->secs = 0;
p->flags = 0;
p->ciaddr = 0;
p->siaddr = 0;
p->giaddr = 0;
}
static int dhcp_prepare_tx(U8 *pOpt, PDHCP_PACKAGE pRsp) {
static PDHCP_PROTO fill_pkg(U8 *pRsp, U8 *pReq) {
U8 *p;
struct ethhdr *pEth = (struct ethhdr *)pReq;
struct iphdr *pIp = NULL;
struct udphdr *pUdp = NULL;
PDHCP_PROTO pDhcp = NULL;
memset(pRsp, 0, MAX_DHCP_PKG_SIZE);
switch (get_package_vlan_type(pReq)) {
default:
pIp = (struct iphdr *)(pReq + IP_HDR_OFFSET);
pUdp = (struct udphdr *)(UDP_HDR_OFFSET);
pDhcp = (PDHCP_PROTO)((U8 *)pReq + DHCP_OFFSET);
p = pRsp + sizeof(struct ethhdr);
break;
case VLAN_LEVEL1:
pIp = (struct iphdr *)(pReq + IP_HDR_OFFSET + sizeof(VLAN_HDR));
pUdp = (struct udphdr *)(pReq + UDP_HDR_OFFSET + sizeof(VLAN_HDR));
pDhcp = (PDHCP_PROTO)((U8 *)pReq + DHCP_OFFSET + sizeof(VLAN_HDR));
add_vlan_head(pRsp, (PVLAN_PKG_HDR1)pReq);
p = pRsp + sizeof(struct ethhdr) + sizeof(VLAN_HDR);
break;
case VLAN_LEVEL2:
pIp = (struct iphdr *)(pReq + IP_HDR_OFFSET + sizeof(VLAN_HDR2));
pUdp = (struct udphdr *)(pReq + UDP_HDR_OFFSET + sizeof(VLAN_HDR2));
pDhcp = (PDHCP_PROTO)((U8 *)pReq + DHCP_OFFSET + sizeof(VLAN_HDR2));
add_vlan2_head(pRsp, (PVLAN_PKG_HDR2)pReq);
p = pRsp + sizeof(struct ethhdr) + sizeof(VLAN_HDR2);
break;
}
add_eth_head(pRsp, pEth, (pIp->saddr == 0) ? TRUE : FALSE);
add_ip_head((struct iphdr *)p, pIp);
p += sizeof(struct iphdr);
add_udp_head((struct udphdr *)p, pUdp);
p += sizeof(struct udphdr);
add_dhcp_common((PDHCP_PROTO)p, pDhcp);
return (PDHCP_PROTO)p;
}
static int dhcp_prepare_tx(U8 *pRsp, U32 optSize) {
struct iphdr *pIp = NULL;
struct udphdr *pUdp = NULL;
U16 csum;
int tolSize;
U32 tolSize;
switch (get_package_vlan_type(pRsp)) {
default:
pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET);
pUdp = (struct udphdr *)(UDP_HDR_OFFSET);
// 计算包总长度
tolSize = (int)((pOpt - pRsp->dhcp.options) + 1 + sizeof(DHCP_PACKAGE));
tolSize = optSize + sizeof(DHCP_PROTO) + DHCP_OFFSET;
break;
case VLAN_LEVEL1:
pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR));
pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR));
// 计算包总长度
tolSize = optSize + sizeof(DHCP_PROTO) + DHCP_OFFSET + sizeof(VLAN_HDR);
break;
case VLAN_LEVEL2:
pIp = (struct iphdr *)(pRsp + IP_HDR_OFFSET + sizeof(VLAN_HDR2));
pUdp = (struct udphdr *)(pRsp + UDP_HDR_OFFSET + sizeof(VLAN_HDR2));
// 计算包总长度
tolSize = optSize + sizeof(DHCP_PROTO) + DHCP_OFFSET + sizeof(VLAN_HDR2);
break;
}
// 计算 IP 数据长度
pRsp->hdr.ip.tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr));
pIp->tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr));
// 计算 UDP 数据长度
pRsp->hdr.udp.len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr));
pUdp->len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr));
// 计算 IP 校验和
csum = htons(ip_checksum((unsigned char *)&pRsp->hdr.ip));
pRsp->hdr.ip.check = htons(csum);
csum = htons(ip_checksum((unsigned char *)pIp));
pIp->check = htons(csum);
// 计算 UDP 校验和
csum = htons(udp_checksum(pRsp->hdr.ip.saddr, pRsp->hdr.ip.daddr, (unsigned char *)&pRsp->hdr.udp));
pRsp->hdr.udp.check = htons(csum);
csum = htons(udp_checksum(pIp->saddr, pIp->daddr, (unsigned char *)pUdp));
pUdp->check = htons(csum);
LOG_MOD(trace, ZM_DHCP_NET, "OPTIONS size: %ld\n", (intptr_t)(pOpt - pRsp->dhcp.options) + 1);
LOG_MOD(trace, ZM_DHCP_NET, "Total size: %d\n", tolSize);
// 发送数据
@ -280,43 +375,45 @@ static int dhcp_prepare_tx(U8 *pOpt, PDHCP_PACKAGE pRsp) {
return ERR_SUCCESS;
}
static int dhcp_resp_nack(PDHCP_PACKAGE pReq) {
static int dhcp_resp_nack(void *pReq) {
U8 *pOpt;
PDHCP_PACKAGE pRsp = get_pkg_free_buf();
PDHCP_PROTO pDhcp = NULL;
U8 *pRsp = get_pkg_free_buf();
if (pRsp == NULL) {
LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
return -ERR_MALLOC_MEMORY;
}
fill_package(pRsp, pReq);
pDhcp = fill_pkg(pRsp, (U8 *)pReq);
// DHCP Options
pOpt = pRsp->dhcp.options;
pOpt = pDhcp->options;
// DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_NAK);
*pOpt = OPT_END;
return dhcp_prepare_tx(pOpt, pRsp);
return dhcp_prepare_tx(pRsp, (int)((pOpt - pDhcp->options) + 1));
}
static int dhcp_resp_ack(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo) {
static int dhcp_resp_ack(void *pReq, PPOOL_CTX pIpInfo) {
U8 *pOpt;
PDHCP_PACKAGE pRsp = get_pkg_free_buf();
PDHCP_PROTO pDhcp = NULL;
U8 *pRsp = get_pkg_free_buf();
if (pRsp == NULL) {
LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
return -ERR_MALLOC_MEMORY;
}
fill_package(pRsp, pReq);
pDhcp = fill_pkg((U8 *)pRsp, (U8 *)pReq);
// 分配的 IP 地址
pRsp->dhcp.yiaddr = htonl(pIpInfo->minAddr);
pDhcp->yiaddr = htonl(pIpInfo->minAddr);
// DHCP Options
pOpt = pRsp->dhcp.options;
pOpt = pDhcp->options;
// DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_ACK);
@ -346,24 +443,26 @@ static int dhcp_resp_ack(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo) {
pOpt += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup");
*pOpt = OPT_END;
return dhcp_prepare_tx(pOpt, pRsp);
return dhcp_prepare_tx(pRsp, (int)((pOpt - pDhcp->options) + 1));
}
static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo, U32 ip) {
static int dhcp_resp_offer(void *pReq, PPOOL_CTX pIpInfo, U32 ip) {
U8 *pOpt;
PDHCP_PACKAGE pRsp = get_pkg_free_buf();
PDHCP_PROTO pDhcp = NULL;
U8 *pRsp = get_pkg_free_buf();
if (pRsp == NULL) {
LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
return -ERR_MALLOC_MEMORY;
}
fill_package(pRsp, pReq);
pDhcp = fill_pkg(pRsp, (U8 *)pReq);
// 分配的 IP 地址
pRsp->dhcp.yiaddr = htonl(ip);
pDhcp->yiaddr = htonl(ip);
// DHCP Options
pOpt = pRsp->dhcp.options;
pOpt = pDhcp->options;
// DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER);
@ -393,10 +492,41 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PPOOL_CTX pIpInfo, U32 ip) {
pOpt += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup");
*pOpt = OPT_END;
return dhcp_prepare_tx(pOpt, pRsp);
return dhcp_prepare_tx(pRsp, (int)((pOpt - pDhcp->options) + 1));
}
static PDHCP_PROTO get_dhcp_date(void *pBuf, U32 *pOptSize, U32 bufSize) {
U8 *p = (U8 *)pBuf;
U32 hdrCom = sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr);
if (p[12] == 0x81 && p[13] == 0x00 && p[16] == 0x81 && p[17] == 0x00) {
*pOptSize = bufSize - hdrCom - sizeof(DHCP_PROTO) - sizeof(VLAN_HDR2);
return (PDHCP_PROTO)(p + hdrCom + 8);
} else if (p[12] == 0x81 && p[13] == 0x00) {
*pOptSize = bufSize - hdrCom - sizeof(DHCP_PROTO) - sizeof(VLAN_HDR);
return (PDHCP_PROTO)(p + hdrCom + 4);
} else {
*pOptSize = bufSize - hdrCom - sizeof(DHCP_PROTO);
return (PDHCP_PROTO)(p + hdrCom);
}
}
U32 dhcp_get_uid(void *pBuf) {
U8 *p = (U8 *)pBuf;
PVLAN_HDR pQinQ = (PVLAN_HDR)(p + sizeof(struct ethhdr));
if (p[12] == 0x81 && p[13] == 0x00 && p[16] == 0x81 && p[17] == 0x00) {
PVLAN_HDR2 pHdr = (PVLAN_HDR2)pQinQ;
return (pHdr->id1 & 0x0FFF) >> 12 | (pHdr->id2 & 0x0FFF) << 12;
} else if (p[12] == 0x81 && p[13] == 0x00) {
return (pQinQ->id & 0x0FFF);
} else {
return 0;
}
}
static void on_sock_recv(uv_work_t *req) {
U32 optSize = 0;
char macStr[20] = {0};
U32 ip;
PPOOL_CTX pIpInfo;
@ -404,62 +534,58 @@ static void on_sock_recv(uv_work_t *req) {
DHCP_OPT optMsg, opt;
int ret;
PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data;
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase;
U32 optSize = pWork->nSize - sizeof(DHCP_PACKAGE);
PDHCP_PROTO pkg = get_dhcp_date(pWork->pPkgBase, &optSize, pWork->nSize);
struct iphdr *pIpHdr = (struct iphdr *)((U8 *)pkg - sizeof(struct iphdr) - sizeof(struct udphdr));
//sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", macStr[0], macStr[1], macStr[2], macStr[3], macStr[4], macStr[5]);
// Check op flag
if (pkg->dhcp.op != BOOTP_REQUEST) {
LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->dhcp.op);
if (pkg->op != BOOTP_REQUEST) {
LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->op);
LOG_MSG_HEX(error, pkg, pWork->nSize);
return;
}
// 获取消息类型
ret = dhcp_get_option(OPT_MESSAGETYPE, pkg->dhcp.options, optSize, &optMsg);
ret = dhcp_get_option(OPT_MESSAGETYPE, pkg->options, optSize, &optMsg);
if (ret != ERR_SUCCESS) {
LOG_MOD(error, ZM_DHCP_NET, "Get \'message type\' option error %d\n", ret);
return;
}
memset(&reqDhcp, 0, sizeof(DHCP_REQ));
reqDhcp.unicast = pkg->dhcp.flags != 0 ? TRUE : FALSE;
reqDhcp.xid = DHCP_XID(pkg->dhcp.xid);
#if VLAN_SUPPORT
reqDhcp.uid = VLAN_VNI_ID(pkg->hdr.vlan.id);
#else
reqDhcp.uid = 0;
#endif
reqDhcp.unicast = pkg->flags != 0 ? TRUE : FALSE;
reqDhcp.xid = DHCP_XID(pkg->xid);
reqDhcp.uid = dhcp_get_uid(pWork->pPkgBase);
reqDhcp.serverAddr = g_nicInfo.ipAddr;
reqDhcp.cliAddr = ntohl(pkg->dhcp.ciaddr);
memcpy(reqDhcp.cliMac, pkg->dhcp.chaddr, ETH_ALEN);
reqDhcp.cliAddr = ntohl(pkg->ciaddr);
memcpy(reqDhcp.cliMac, pkg->chaddr, ETH_ALEN);
MAC_TO_STR(reqDhcp.cliMac, macStr);
switch (*optMsg.pValue) {
case DHCP_MSG_DISCOVER:
case DHCP_MSG_DSCIOVER:
// region DHCP Discover 处理
ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqIpAddr = ntohl(*((U32 *)opt.pValue));
}
ret = dhcp_get_option(OPT_IPADDRLEASE, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_IPADDRLEASE, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.leaseTime = ntohl(*((U32 *)opt.pValue));
}
ret = dhcp_get_option(OPT_CLIENTID, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_CLIENTID, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.clientId, (char *)opt.pValue, MIN((int)opt.len, 256));
}
ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.vendorClassId, (char *)opt.pValue, MIN((int)opt.len, 256));
}
ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_HOSTNAME, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256));
}
@ -470,7 +596,7 @@ static void on_sock_recv(uv_work_t *req) {
LOG_MOD(debug, ZM_DHCP_NET, "User %u DHCP prepare assign ipaddress: [%s(%s)] --> %s\n", reqDhcp.uid,
macStr, reqDhcp.hostName, u32_to_str_ip(ntohl(ip)));
ret = dhcp_resp_offer(pkg, pIpInfo, ip);
ret = dhcp_resp_offer(pWork->pPkgBase, pIpInfo, ip);
if (ret != ERR_SUCCESS) {
LOG_MOD(error, ZM_DHCP_NET, "Send Offer error: %d\n", ret);
}
@ -479,7 +605,7 @@ static void on_sock_recv(uv_work_t *req) {
reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret));
// Send NACK
ret = dhcp_resp_nack(pkg);
ret = dhcp_resp_nack(pWork->pPkgBase);
}
if (ret != ERR_SUCCESS) {
@ -490,18 +616,18 @@ static void on_sock_recv(uv_work_t *req) {
case DHCP_MSG_REQUEST:
// region DHCP Request 处理
// 客户端请求的服务器
ret = dhcp_get_option(OPT_SERVERID, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_SERVERID, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue));
} else {
// Request 服务器IP可以取目的 IP 地址
if (pkg->hdr.ip.saddr != 0) {
reqDhcp.reqServer = ntohl(pkg->hdr.ip.daddr);
if (pIpHdr->saddr != 0) {
reqDhcp.reqServer = ntohl(pIpHdr->daddr);
}
}
// 客户端请求的IP
ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqIpAddr = ntohl(*((U32 *)opt.pValue));
} else {
@ -509,7 +635,7 @@ static void on_sock_recv(uv_work_t *req) {
}
// 客户端主机名
ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_HOSTNAME, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256));
}
@ -529,12 +655,12 @@ static void on_sock_recv(uv_work_t *req) {
LOG_MOD(debug, ZM_DHCP_NET, "User %u DHCP assign ipaddress: [%s(%s)] --> %s\n", reqDhcp.uid, macStr,
reqDhcp.hostName, u32_to_str_ip(ntohl(ctx.minAddr)));
ret = dhcp_resp_ack(pkg, &ctx);
ret = dhcp_resp_ack(pWork->pPkgBase, &ctx);
} else {
LOG_MOD(error, ZM_DHCP_NET, "DHCP assign ipaddress error: User %u [%s(%s)] resion %s\n",
reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret));
// Send NACK
ret = dhcp_resp_nack(pkg);
ret = dhcp_resp_nack(pWork->pPkgBase);
}
if (ret != ERR_SUCCESS) {
@ -546,17 +672,17 @@ static void on_sock_recv(uv_work_t *req) {
case DHCP_MSG_RELEASE:
// region DHCP Release 处理
// 客户端请求的服务器
ret = dhcp_get_option(OPT_SERVERID, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_SERVERID, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue));
} else {
// Request 服务器IP可以取目的 IP 地址
if (pkg->hdr.ip.saddr != 0) {
reqDhcp.reqServer = ntohl(pkg->hdr.ip.saddr);
if (pIpHdr->saddr != 0) {
reqDhcp.reqServer = ntohl(pIpHdr->saddr);
}
}
reqDhcp.reqIpAddr = ntohl(pkg->dhcp.ciaddr);
reqDhcp.reqIpAddr = ntohl(pkg->ciaddr);
lease_release(&reqDhcp);
LOG_MOD(debug, ZM_DHCP_NET, "User %u DHCP release lease: [%s(%s)] --> %s\n", reqDhcp.uid, macStr,
@ -565,7 +691,7 @@ static void on_sock_recv(uv_work_t *req) {
break;
case DHCP_MSG_INFORM:
// 客户端主机名
ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt);
ret = dhcp_get_option(OPT_HOSTNAME, pkg->options, optSize, &opt);
if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256));
}
@ -591,14 +717,14 @@ static void on_sock_recv(uv_work_t *req) {
break;
}
//dhcp_option_prase(optMsg, pkg->dhcp.options, pWork->nSize - sizeof(DHCP_PACKAGE));
//dhcp_option_prase(optMsg, pkg->options, pWork->nSize - sizeof(DHCP_PACKAGE));
LOG_MSG_HEX(trace, pkg, pWork->nSize);
//LOG_MSG(info, "vni: %d, xid: 0x%08X\n", VLAN_VNI_ID(pkg->hdr.vlan.id), DHCP_XID(pkg->dhcp.xid));
//LOG_MSG(info, "vni: %d, xid: 0x%08X\n", VLAN_VNI_ID(pkg->hdr.vlan.id), DHCP_XID(pkg->xid));
#if 0
LOG_MOD(info, ZM_DHCP_NET, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->hdr.vlan.id));
LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid));
LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->xid));
LOG_MSG(info,
"dest mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
pkg->hdr.eth.h_dest[0],
@ -609,16 +735,16 @@ static void on_sock_recv(uv_work_t *req) {
pkg->hdr.eth.h_dest[5]);
LOG_MSG(info,
"client mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
pkg->dhcp.chaddr[0],
pkg->dhcp.chaddr[1],
pkg->dhcp.chaddr[2],
pkg->dhcp.chaddr[3],
pkg->dhcp.chaddr[4],
pkg->dhcp.chaddr[5]);
pkg->chaddr[0],
pkg->chaddr[1],
pkg->chaddr[2],
pkg->chaddr[3],
pkg->chaddr[4],
pkg->chaddr[5]);
#endif
}
static void after_msg_recv(uv_work_t *req, int status) {
static void after_msg_recv(uv_work_t *req, int UNUSED(status)) {
PPKG_PROCESS_INFO pInfo = (PPKG_PROCESS_INFO)req->data;
PPKG_MSG pMsg = (PPKG_MSG)pInfo->pData;
@ -662,19 +788,14 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) {
pMsg->nf = pbd->h1.num_pkts;
ppd = (struct tpacket3_hdr *)((uint8_t *)pbd + pbd->h1.offset_to_first_pkt);
for (i = 0; i < pbd->h1.num_pkts; i++) {
PDHCP_PACKAGE pkg;
U32 uid;
pMsg->pPkgInfo[i].pPkgBase = ((uint8_t *)ppd + ppd->tp_mac);
pMsg->pPkgInfo[i].nSize = ppd->tp_snaplen;
pMsg->pPkgInfo[i].uvWork.data = &pMsg->pPkgInfo[i];
pMsg->pPkgInfo[i].pData = pMsg;
if (g_dhcpMode == MODE_DHCP_SERVER) {
#if VLAN_SUPPORT
pkg = (PDHCP_PACKAGE)pMsg->pPkgInfo[i].pPkgBase;
uid = VLAN_VNI_ID(pkg->hdr.vlan.id);
#else
uid = 0;
#endif
uid = dhcp_get_uid(pMsg->pPkgInfo[i].pPkgBase);
pMsg->pPkgInfo[i].pUser = dhcp_user_create(uid);
// LOG_MOD(trace, ZM_DHCP_NET, ">>> User %u xid %08X addr %p\n", uid, DHCP_XID(pkg->dhcp.xid),

View File

@ -53,7 +53,7 @@ typedef struct {
#pragma pack(1)
typedef struct {
VLAN_PKG_HDR hdr;
VLAN_PKG_HDR1 hdr;
DHCP_PROTO dhcp;
} DHCP_PACKAGE, *PDHCP_PACKAGE;

View File

@ -95,18 +95,14 @@ int pre_alloc_dhcp_res(PDHCP_REQ pReq, PDHCP_USER pUser, U32 *pOutIp, PPOOL_CTX
addr = pPool->minAddr;
do {
PLOCK_IP pLock;
HASH_FIND_INT(pUser->plockIp, &addr, pLock);
// 该 IP 可用
if (pLock == NULL) {
if (db_ip_is_pre_assign(pReq->uid, addr) == FALSE) {
usr_lease_lock_ip(pUser, addr);
*pOutIp = addr;
*pOutPool = pPool;
db_add_pre_assign(pReq, addr, pPool);
return ERR_SUCCESS;
}
}