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) #define VXLAN_VIN_ID_PACK(x) ((ntohs(x)) & 0xFFF)
typedef enum {
VLAN_NONE,
VLAN_LEVEL1,
VLAN_LEVEL2
} VLAN_TYPE;
typedef struct vlan_hdr { typedef struct vlan_hdr {
#if VLAN_SUPPORT #if VLAN_SUPPORT
U16 id; U16 id;
@ -27,6 +33,21 @@ typedef struct vlan_hdr {
#endif #endif
} VLAN_HDR, *PVLAN_HDR; } 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 { typedef struct {
struct ethhdr eth; struct ethhdr eth;
#if VLAN_SUPPORT #if VLAN_SUPPORT
@ -34,7 +55,16 @@ typedef struct {
#endif #endif
struct iphdr ip; struct iphdr ip;
struct udphdr udp; 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) #pragma pack(pop)
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -15,7 +15,7 @@
// 10小时以上清理无效的预分配IP // 10小时以上清理无效的预分配IP
#define DCHP_STEP_CLEANUP_TIMEOUT (36000) #define DCHP_STEP_CLEANUP_TIMEOUT (36000)
// Discover 预分配IP 和Request 请求间的超时时间 // Discover 预分配IP 和 Request 请求间的超时时间
#define DCHP_STEP_REQUEST_TIMEOUT (600000) #define DCHP_STEP_REQUEST_TIMEOUT (600000)
#define CREATE_LEASE_TABLE() \ #define CREATE_LEASE_TABLE() \
@ -114,7 +114,6 @@
#define LEASE_RELEASE_FMT "DELETE FROM lease WHERE uid = %d AND mac = '%s' AND ip = '%s'" #define LEASE_RELEASE_FMT "DELETE FROM lease WHERE uid = %d AND mac = '%s' AND ip = '%s'"
static int lease_add(PDHCP_REQ pReq, static int lease_add(PDHCP_REQ pReq,
const char *ip, const char *ip,
const char *netmask, 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)); const char *pIp = u32_to_str_ip_safe(htonl(pAssign->minAddr));
// 删除预分配IP信息 // 删除预分配IP信息
#if 0
memset(buf, 0, 2048); memset(buf, 0, 2048);
sprintf(buf, "DELETE FROM pre_assign WHERE id = %llu;", id); sprintf(buf, "DELETE FROM pre_assign WHERE id = %llu;", id);
db_sqlite3_sql_exec(buf, NULL, NULL, NULL); db_sqlite3_sql_exec(buf, NULL, NULL, NULL);
#endif
// 添加租约信息到lease数据库 // 添加租约信息到lease数据库
lease_add(pReq, pIp, pNetmask, pGateway, pDns1, pDns2, pAssign->leaseTime); 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_SUCCESS;
} }
return -ERR_ITEM_UNEXISTS; 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) { 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 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 TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are
responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT 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 uv_udp_t g_uvRawSockReq;
static DHCP_WORK_MODE g_dhcpMode; 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() { U32 dhcp_get_default_netmask() {
return g_nicInfo.netmask; return g_nicInfo.netmask;
} }
@ -182,93 +198,172 @@ U32 pkg_mmap_tx(U8 *pData, U32 nBytes) {
return hdr->tp_len; return hdr->tp_len;
} }
static void fill_package(PDHCP_PACKAGE pRsp, PDHCP_PACKAGE pReq) { static void add_eth_head(U8 *pRsp, struct ethhdr *pEth, int isBst) {
memset(pRsp, 0, MAX_DHCP_PKG_SIZE); struct ethhdr *p = (struct ethhdr *)pRsp;
// 二层头 // 二层头
// 目的IP地址 // 目的 MAC 地址
if (pReq->hdr.ip.saddr != 0) { if (!isBst) {
memcpy(pRsp->hdr.eth.h_dest, pRsp->hdr.eth.h_source, ETH_ALEN); memcpy(p->h_dest, pEth->h_source, ETH_ALEN);
} else { } else {
memset(pRsp->hdr.eth.h_dest, 0xFF, ETH_ALEN); memset(p->h_dest, 0xFF, ETH_ALEN);
} }
// 源 IP 地址 // 源 MAC 地址
memcpy(pRsp->hdr.eth.h_source, g_nicInfo.macAddr, ETH_ALEN); memcpy(p->h_source, g_nicInfo.macAddr, ETH_ALEN);
// protol // protol
pRsp->hdr.eth.h_proto = pReq->hdr.eth.h_proto; 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;
#if VLAN_SUPPORT
// QinQ 隧道 // QinQ 隧道
pRsp->hdr.vlan.id = pReq->hdr.vlan.id; p->vlan.id = pvHdr->vlan.id;
pRsp->hdr.vlan.type = pReq->hdr.vlan.type; p->vlan.type = pvHdr->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;
}
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 头 // 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 协议 //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 // xid
pRsp->dhcp.xid = pReq->dhcp.xid; p->xid = pDhcp->xid;
// 客户端 MAC 地址 // 客户端 MAC 地址
memcpy(pRsp->dhcp.chaddr, pReq->dhcp.chaddr, ETH_ALEN); memcpy(p->chaddr, pDhcp->chaddr, ETH_ALEN);
// DHCP服务端主机名 // 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 // Magic Cookie: DHCP
// //
// memcpy(&pRsp->dhcp.cookie, DHCP_COOKIE_VAL, 4); // 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; p->hops = 0;
pRsp->dhcp.secs = 0; p->secs = 0;
pRsp->dhcp.flags = 0; p->flags = 0;
pRsp->dhcp.ciaddr = 0; p->ciaddr = 0;
pRsp->dhcp.siaddr = 0; p->siaddr = 0;
pRsp->dhcp.giaddr = 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; 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 数据长度 // 计算 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 数据长度 // 计算 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 校验和 // 计算 IP 校验和
csum = htons(ip_checksum((unsigned char *)&pRsp->hdr.ip)); csum = htons(ip_checksum((unsigned char *)pIp));
pRsp->hdr.ip.check = htons(csum); pIp->check = htons(csum);
// 计算 UDP 校验和 // 计算 UDP 校验和
csum = htons(udp_checksum(pRsp->hdr.ip.saddr, pRsp->hdr.ip.daddr, (unsigned char *)&pRsp->hdr.udp)); csum = htons(udp_checksum(pIp->saddr, pIp->daddr, (unsigned char *)pUdp));
pRsp->hdr.udp.check = htons(csum); 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); 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; return ERR_SUCCESS;
} }
static int dhcp_resp_nack(PDHCP_PACKAGE pReq) { static int dhcp_resp_nack(void *pReq) {
U8 *pOpt; U8 *pOpt;
PDHCP_PACKAGE pRsp = get_pkg_free_buf(); PDHCP_PROTO pDhcp = NULL;
U8 *pRsp = get_pkg_free_buf();
if (pRsp == NULL) { if (pRsp == NULL) {
LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE); LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
return -ERR_MALLOC_MEMORY; return -ERR_MALLOC_MEMORY;
} }
fill_package(pRsp, pReq); pDhcp = fill_pkg(pRsp, (U8 *)pReq);
// DHCP Options // DHCP Options
pOpt = pRsp->dhcp.options; pOpt = pDhcp->options;
// DHCP 消息类型 // DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_NAK); pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_NAK);
*pOpt = OPT_END; *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; U8 *pOpt;
PDHCP_PACKAGE pRsp = get_pkg_free_buf(); PDHCP_PROTO pDhcp = NULL;
U8 *pRsp = get_pkg_free_buf();
if (pRsp == NULL) { if (pRsp == NULL) {
LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE); LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
return -ERR_MALLOC_MEMORY; return -ERR_MALLOC_MEMORY;
} }
fill_package(pRsp, pReq); pDhcp = fill_pkg((U8 *)pRsp, (U8 *)pReq);
// 分配的 IP 地址 // 分配的 IP 地址
pRsp->dhcp.yiaddr = htonl(pIpInfo->minAddr); pDhcp->yiaddr = htonl(pIpInfo->minAddr);
// DHCP Options // DHCP Options
pOpt = pRsp->dhcp.options; pOpt = pDhcp->options;
// DHCP 消息类型 // DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_ACK); 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 += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup");
*pOpt = OPT_END; *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; U8 *pOpt;
PDHCP_PACKAGE pRsp = get_pkg_free_buf(); PDHCP_PROTO pDhcp = NULL;
U8 *pRsp = get_pkg_free_buf();
if (pRsp == NULL) { if (pRsp == NULL) {
LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE); LOG_MOD(error, ZM_DHCP_NET, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
return -ERR_MALLOC_MEMORY; return -ERR_MALLOC_MEMORY;
} }
fill_package(pRsp, pReq); pDhcp = fill_pkg(pRsp, (U8 *)pReq);
// 分配的 IP 地址 // 分配的 IP 地址
pRsp->dhcp.yiaddr = htonl(ip); pDhcp->yiaddr = htonl(ip);
// DHCP Options // DHCP Options
pOpt = pRsp->dhcp.options; pOpt = pDhcp->options;
// DHCP 消息类型 // DHCP 消息类型
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER); 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 += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup");
*pOpt = OPT_END; *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) { static void on_sock_recv(uv_work_t *req) {
U32 optSize = 0;
char macStr[20] = {0}; char macStr[20] = {0};
U32 ip; U32 ip;
PPOOL_CTX pIpInfo; PPOOL_CTX pIpInfo;
@ -404,62 +534,58 @@ static void on_sock_recv(uv_work_t *req) {
DHCP_OPT optMsg, opt; DHCP_OPT optMsg, opt;
int ret; int ret;
PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data; PPKG_PROCESS_INFO pWork = (PPKG_PROCESS_INFO)req->data;
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase; PDHCP_PROTO pkg = get_dhcp_date(pWork->pPkgBase, &optSize, pWork->nSize);
U32 optSize = pWork->nSize - sizeof(DHCP_PACKAGE); 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]); //sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", macStr[0], macStr[1], macStr[2], macStr[3], macStr[4], macStr[5]);
// Check op flag // Check op flag
if (pkg->dhcp.op != BOOTP_REQUEST) { if (pkg->op != BOOTP_REQUEST) {
LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->dhcp.op); LOG_MOD(error, ZM_DHCP_NET, "Error message op code %d\n", pkg->op);
LOG_MSG_HEX(error, pkg, pWork->nSize); LOG_MSG_HEX(error, pkg, pWork->nSize);
return; 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) { if (ret != ERR_SUCCESS) {
LOG_MOD(error, ZM_DHCP_NET, "Get \'message type\' option error %d\n", ret); LOG_MOD(error, ZM_DHCP_NET, "Get \'message type\' option error %d\n", ret);
return; return;
} }
memset(&reqDhcp, 0, sizeof(DHCP_REQ)); memset(&reqDhcp, 0, sizeof(DHCP_REQ));
reqDhcp.unicast = pkg->dhcp.flags != 0 ? TRUE : FALSE; reqDhcp.unicast = pkg->flags != 0 ? TRUE : FALSE;
reqDhcp.xid = DHCP_XID(pkg->dhcp.xid); reqDhcp.xid = DHCP_XID(pkg->xid);
#if VLAN_SUPPORT reqDhcp.uid = dhcp_get_uid(pWork->pPkgBase);
reqDhcp.uid = VLAN_VNI_ID(pkg->hdr.vlan.id);
#else
reqDhcp.uid = 0;
#endif
reqDhcp.serverAddr = g_nicInfo.ipAddr; reqDhcp.serverAddr = g_nicInfo.ipAddr;
reqDhcp.cliAddr = ntohl(pkg->dhcp.ciaddr); reqDhcp.cliAddr = ntohl(pkg->ciaddr);
memcpy(reqDhcp.cliMac, pkg->dhcp.chaddr, ETH_ALEN); memcpy(reqDhcp.cliMac, pkg->chaddr, ETH_ALEN);
MAC_TO_STR(reqDhcp.cliMac, macStr); MAC_TO_STR(reqDhcp.cliMac, macStr);
switch (*optMsg.pValue) { switch (*optMsg.pValue) {
case DHCP_MSG_DISCOVER: case DHCP_MSG_DSCIOVER:
// region DHCP Discover 处理 // 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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqIpAddr = ntohl(*((U32 *)opt.pValue)); 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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.leaseTime = ntohl(*((U32 *)opt.pValue)); 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) { if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.clientId, (char *)opt.pValue, MIN((int)opt.len, 256)); 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) { if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.vendorClassId, (char *)opt.pValue, MIN((int)opt.len, 256)); 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) { if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256)); 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, 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))); 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) { if (ret != ERR_SUCCESS) {
LOG_MOD(error, ZM_DHCP_NET, "Send Offer error: %d\n", ret); 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)); reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret));
// Send NACK // Send NACK
ret = dhcp_resp_nack(pkg); ret = dhcp_resp_nack(pWork->pPkgBase);
} }
if (ret != ERR_SUCCESS) { if (ret != ERR_SUCCESS) {
@ -490,18 +616,18 @@ static void on_sock_recv(uv_work_t *req) {
case DHCP_MSG_REQUEST: case DHCP_MSG_REQUEST:
// region DHCP 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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue)); reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue));
} else { } else {
// Request 服务器IP可以取目的 IP 地址 // Request 服务器IP可以取目的 IP 地址
if (pkg->hdr.ip.saddr != 0) { if (pIpHdr->saddr != 0) {
reqDhcp.reqServer = ntohl(pkg->hdr.ip.daddr); reqDhcp.reqServer = ntohl(pIpHdr->daddr);
} }
} }
// 客户端请求的IP // 客户端请求的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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqIpAddr = ntohl(*((U32 *)opt.pValue)); reqDhcp.reqIpAddr = ntohl(*((U32 *)opt.pValue));
} else { } 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) { if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256)); 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, 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))); reqDhcp.hostName, u32_to_str_ip(ntohl(ctx.minAddr)));
ret = dhcp_resp_ack(pkg, &ctx); ret = dhcp_resp_ack(pWork->pPkgBase, &ctx);
} else { } else {
LOG_MOD(error, ZM_DHCP_NET, "DHCP assign ipaddress error: User %u [%s(%s)] resion %s\n", LOG_MOD(error, ZM_DHCP_NET, "DHCP assign ipaddress error: User %u [%s(%s)] resion %s\n",
reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret)); reqDhcp.uid, macStr, reqDhcp.hostName, getErrorEnumNameString(ret));
// Send NACK // Send NACK
ret = dhcp_resp_nack(pkg); ret = dhcp_resp_nack(pWork->pPkgBase);
} }
if (ret != ERR_SUCCESS) { if (ret != ERR_SUCCESS) {
@ -546,17 +672,17 @@ static void on_sock_recv(uv_work_t *req) {
case DHCP_MSG_RELEASE: case DHCP_MSG_RELEASE:
// region DHCP 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)) { if (ret == ERR_SUCCESS && opt.len == sizeof(U32)) {
reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue)); reqDhcp.reqServer = ntohl(*((U32 *)opt.pValue));
} else { } else {
// Request 服务器IP可以取目的 IP 地址 // Request 服务器IP可以取目的 IP 地址
if (pkg->hdr.ip.saddr != 0) { if (pIpHdr->saddr != 0) {
reqDhcp.reqServer = ntohl(pkg->hdr.ip.saddr); reqDhcp.reqServer = ntohl(pIpHdr->saddr);
} }
} }
reqDhcp.reqIpAddr = ntohl(pkg->dhcp.ciaddr); reqDhcp.reqIpAddr = ntohl(pkg->ciaddr);
lease_release(&reqDhcp); lease_release(&reqDhcp);
LOG_MOD(debug, ZM_DHCP_NET, "User %u DHCP release lease: [%s(%s)] --> %s\n", reqDhcp.uid, macStr, 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; break;
case DHCP_MSG_INFORM: 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) { if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256)); 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; 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_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 #if 0
LOG_MOD(info, ZM_DHCP_NET, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->hdr.vlan.id)); 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, LOG_MSG(info,
"dest mac: %02X:%02X:%02X:%02X:%02X:%02X\n", "dest mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
pkg->hdr.eth.h_dest[0], 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]); pkg->hdr.eth.h_dest[5]);
LOG_MSG(info, LOG_MSG(info,
"client mac: %02X:%02X:%02X:%02X:%02X:%02X\n", "client mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
pkg->dhcp.chaddr[0], pkg->chaddr[0],
pkg->dhcp.chaddr[1], pkg->chaddr[1],
pkg->dhcp.chaddr[2], pkg->chaddr[2],
pkg->dhcp.chaddr[3], pkg->chaddr[3],
pkg->dhcp.chaddr[4], pkg->chaddr[4],
pkg->dhcp.chaddr[5]); pkg->chaddr[5]);
#endif #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_PROCESS_INFO pInfo = (PPKG_PROCESS_INFO)req->data;
PPKG_MSG pMsg = (PPKG_MSG)pInfo->pData; 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; pMsg->nf = pbd->h1.num_pkts;
ppd = (struct tpacket3_hdr *)((uint8_t *)pbd + pbd->h1.offset_to_first_pkt); ppd = (struct tpacket3_hdr *)((uint8_t *)pbd + pbd->h1.offset_to_first_pkt);
for (i = 0; i < pbd->h1.num_pkts; i++) { for (i = 0; i < pbd->h1.num_pkts; i++) {
PDHCP_PACKAGE pkg;
U32 uid; U32 uid;
pMsg->pPkgInfo[i].pPkgBase = ((uint8_t *)ppd + ppd->tp_mac); pMsg->pPkgInfo[i].pPkgBase = ((uint8_t *)ppd + ppd->tp_mac);
pMsg->pPkgInfo[i].nSize = ppd->tp_snaplen; pMsg->pPkgInfo[i].nSize = ppd->tp_snaplen;
pMsg->pPkgInfo[i].uvWork.data = &pMsg->pPkgInfo[i]; pMsg->pPkgInfo[i].uvWork.data = &pMsg->pPkgInfo[i];
pMsg->pPkgInfo[i].pData = pMsg; pMsg->pPkgInfo[i].pData = pMsg;
if (g_dhcpMode == MODE_DHCP_SERVER) { if (g_dhcpMode == MODE_DHCP_SERVER) {
#if VLAN_SUPPORT uid = dhcp_get_uid(pMsg->pPkgInfo[i].pPkgBase);
pkg = (PDHCP_PACKAGE)pMsg->pPkgInfo[i].pPkgBase;
uid = VLAN_VNI_ID(pkg->hdr.vlan.id);
#else
uid = 0;
#endif
pMsg->pPkgInfo[i].pUser = dhcp_user_create(uid); 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), // 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) #pragma pack(1)
typedef struct { typedef struct {
VLAN_PKG_HDR hdr; VLAN_PKG_HDR1 hdr;
DHCP_PROTO dhcp; DHCP_PROTO dhcp;
} DHCP_PACKAGE, *PDHCP_PACKAGE; } 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; addr = pPool->minAddr;
do { do {
PLOCK_IP pLock; PLOCK_IP pLock;
HASH_FIND_INT(pUser->plockIp, &addr, pLock); HASH_FIND_INT(pUser->plockIp, &addr, pLock);
// 该 IP 可用 // 该 IP 可用
if (pLock == NULL) { if (pLock == NULL) {
if (db_ip_is_pre_assign(pReq->uid, addr) == FALSE) { if (db_ip_is_pre_assign(pReq->uid, addr) == FALSE) {
usr_lease_lock_ip(pUser, addr); usr_lease_lock_ip(pUser, addr);
*pOutIp = addr; *pOutIp = addr;
*pOutPool = pPool; *pOutPool = pPool;
db_add_pre_assign(pReq, addr, pPool); db_add_pre_assign(pReq, addr, pPool);
return ERR_SUCCESS; return ERR_SUCCESS;
} }
} }