OCT 1. DHCP 服务支持自动识别VLAN、单层QinQ, 双层QinQ头部
This commit is contained in:
parent
a5d99d5dba
commit
958fbab193
|
@ -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
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
// 10小时以上清理无效的预分配IP
|
||||
#define DCHP_STEP_CLEANUP_TIMEOUT (36000)
|
||||
// Discover 预分配IP 和Request 请求间的超时时间
|
||||
// Discover 预分配IP 和 Request 请求间的超时时间
|
||||
#define DCHP_STEP_REQUEST_TIMEOUT (600000)
|
||||
|
||||
#define CREATE_LEASE_TABLE() \
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
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 隧道
|
||||
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->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),
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue