Merge branch 'libuv_dhcpd_dev' of http://git.komect.net/ZNJK/vcpe into v1.2.0_dev
This commit is contained in:
commit
063157c199
|
@ -72,7 +72,7 @@ BreakConstructorInitializersBeforeComma: false
|
|||
BreakConstructorInitializers: BeforeColon
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 140
|
||||
ColumnLimit: 120
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
|
|
|
@ -42,6 +42,8 @@ int process_lock_pidfile(char *pFilePath);
|
|||
void process_unlock_pidfile();
|
||||
int get_all_network_info(PSYS_NIC_INFO pInfo);
|
||||
const char *u32_to_str_ip(unsigned int ip);
|
||||
unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp);
|
||||
unsigned short ip_checksum(unsigned char *pIp);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -70,6 +70,7 @@ extern "C" {
|
|||
ERR_CODE(ERR_DHCP_NO_POOL, "找不到可用地址池") \
|
||||
ERR_CODE(ERR_DHCP_NO_ADDR, "找不到可用IP地址") \
|
||||
ERR_CODE(ERR_SOCK_CREATE, "创建套接字失败") \
|
||||
ERR_CODE(ERR_SOCK_SEND, "套接字发送数据失败") \
|
||||
ERR_CODE(ERR_SOCK_SETOPT, "设置套接字参数失败")
|
||||
|
||||
#define GENERATE_ENUM(ENUM, x) ENUM,
|
||||
|
|
|
@ -11,12 +11,13 @@
|
|||
#include <sys/ioctl.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip.h>
|
||||
|
||||
#include "user_errno.h"
|
||||
#include "misc.h"
|
||||
#include "zlog_module.h"
|
||||
#include "common.h"
|
||||
#include "uthash/uthash.h"
|
||||
|
||||
PSYS_NIC_INFO g_sysNicInfo = NULL;
|
||||
|
||||
|
@ -365,3 +366,53 @@ const char *get_cur_process_name() {
|
|||
|
||||
return basename_v2(g_exeName);
|
||||
}
|
||||
|
||||
unsigned short calc_checksum(unsigned short *buffer, int size, U32 sum) {
|
||||
unsigned long cksum = ((sum & 0xFFFF0000) >> 16) + (sum & 0xFFFF);
|
||||
|
||||
while (size > 1) {
|
||||
cksum += *buffer++;
|
||||
size -= sizeof(unsigned short);
|
||||
}
|
||||
|
||||
if (size) {
|
||||
cksum += *(unsigned short *)buffer;
|
||||
}
|
||||
|
||||
cksum = (cksum >> 16) + (cksum & 0xffff);
|
||||
cksum += (cksum >> 16);
|
||||
|
||||
return cksum;
|
||||
//return (unsigned short)(~cksum);
|
||||
}
|
||||
|
||||
unsigned short ip_checksum(unsigned char *pIp) {
|
||||
unsigned int csum;
|
||||
struct iphdr *pIph = (struct iphdr *)pIp;
|
||||
pIph->check = 0;
|
||||
|
||||
csum = calc_checksum((unsigned short *)pIp, 20, 0);
|
||||
|
||||
csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF);
|
||||
return (unsigned short)(~csum);
|
||||
}
|
||||
|
||||
unsigned short udp_checksum(unsigned int saddr, unsigned int daddr, unsigned char *pUdp) {
|
||||
unsigned char padBuf[12];
|
||||
unsigned int csum;
|
||||
struct udphdr *pUhd = (struct udphdr *)pUdp;
|
||||
|
||||
memcpy(&padBuf[0], &saddr, 4);
|
||||
memcpy(&padBuf[4], &daddr, 4);
|
||||
padBuf[8] = 0;
|
||||
padBuf[9] = 17;
|
||||
padBuf[10] = pUdp[4];
|
||||
padBuf[11] = pUdp[5];
|
||||
|
||||
pUhd->check = 0;
|
||||
csum = calc_checksum((unsigned short *)pUdp, ntohs(pUhd->len), 0);
|
||||
csum = calc_checksum((unsigned short *)padBuf, 12, csum);
|
||||
|
||||
csum = ((csum & 0xFFFF0000) >> 16) + (csum & 0xFFFF);
|
||||
return (unsigned short)(~csum);
|
||||
}
|
|
@ -141,22 +141,39 @@ void dhcp_option_cfg_init() {
|
|||
}
|
||||
}
|
||||
|
||||
void dhcp_add_number_option(U8 *pBegin, int opt, U8 value, U8 nSize) {
|
||||
int dhcp_add_u8_option(U8 *pBegin, int opt, U8 value) {
|
||||
*pBegin = opt;
|
||||
pBegin++;
|
||||
*pBegin = nSize;
|
||||
*pBegin = 1;
|
||||
pBegin++;
|
||||
memcpy(pBegin, &value, nSize);
|
||||
pBegin += nSize;
|
||||
*pBegin = value;
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
void dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize) {
|
||||
int dhcp_add_u32_option(U8 *pBegin, int opt, U32 value) {
|
||||
*pBegin = opt;
|
||||
pBegin++;
|
||||
*pBegin = 4;
|
||||
pBegin++;
|
||||
memcpy(pBegin, &value, 4);
|
||||
return 4 + 2;
|
||||
}
|
||||
|
||||
int dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize) {
|
||||
*pBegin = opt;
|
||||
pBegin++;
|
||||
*pBegin = nSize;
|
||||
pBegin++;
|
||||
memcpy(pBegin, buf, nSize);
|
||||
pBegin += nSize;
|
||||
|
||||
return nSize + 2;
|
||||
}
|
||||
|
||||
int dhcp_add_string_option(U8 *pBegin, int opt, const char *buf) {
|
||||
dhcp_add_buf_option(pBegin, opt, (U8 *)buf, strlen(buf) + 1);
|
||||
return (int)(strlen(buf) + 1 + 2);
|
||||
}
|
||||
|
||||
int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) {
|
||||
|
@ -177,8 +194,6 @@ int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) {
|
|||
if (g_optRuntime[id].enable && id == opt) {
|
||||
pVal->len = len;
|
||||
pVal->pValue = p + 2;
|
||||
|
||||
printf("++++ %d size %d\n", id, len);
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,12 +21,16 @@
|
|||
#include "misc.h"
|
||||
#include "user_mgr.h"
|
||||
|
||||
#define DHCP_COOKIE_VAL (0x63825363)
|
||||
#define PKG_MMAP_BLOCKSIZ (1 << 22)
|
||||
#define PKG_MMAP_FRAMESIZ (1 << 11)
|
||||
#define PKG_MMAP_BLOCKNUM (64)
|
||||
#define MAX_DHCP_PKG_SIZE (512)
|
||||
#define VLAN_VNI_ID(x) ntohs((x))
|
||||
#define DHCP_XID(x) ntohl((x))
|
||||
|
||||
#define MAC_TO_STR(mac, str) sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
|
||||
#define MAC_TO_STR(mac, str) \
|
||||
sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
|
||||
|
||||
typedef struct {
|
||||
U8 unicast;
|
||||
|
@ -40,9 +44,15 @@ typedef struct {
|
|||
} DHCP_REQ, *PDHCP_REQ;
|
||||
|
||||
typedef struct {
|
||||
struct iovec *rd;
|
||||
uint8_t *map;
|
||||
struct tpacket_req3 req;
|
||||
int sock;
|
||||
struct sockaddr_ll addr;
|
||||
struct iovec *rx;
|
||||
struct iovec *tx;
|
||||
uint8_t *map_recv;
|
||||
uint8_t *map_send;
|
||||
struct tpacket_req3 recv;
|
||||
struct tpacket_req3 send;
|
||||
unsigned int index;
|
||||
} PACKET_MMAP_RING, *PPACKET_MMAP_RING;
|
||||
|
||||
typedef struct {
|
||||
|
@ -201,16 +211,39 @@ static struct sock_filter g_filterCode[] = {
|
|||
|
||||
static PACKET_MMAP_RING g_pkgRing;
|
||||
static NIC_INFO g_nicInfo;
|
||||
|
||||
#define VLAN_VNI_ID(x) ntohs((x))
|
||||
#define DHCP_XID(x) ntohl((x))
|
||||
static uv_udp_t g_uvRawScokReq;
|
||||
|
||||
static struct sock_fprog bpf = {
|
||||
.len = sizeof(g_filterCode) / (sizeof(struct sock_filter)),
|
||||
.filter = g_filterCode,
|
||||
};
|
||||
|
||||
U32 pkg_mmap_tx(U8 *pData, U32 nBytes) {
|
||||
int i;
|
||||
ssize_t ret;
|
||||
struct tpacket3_hdr *hdr;
|
||||
|
||||
for (i = 0; i < g_pkgRing.send.tp_frame_nr; i++) {
|
||||
hdr = (struct tpacket3_hdr *)(g_pkgRing.tx[0].iov_base + (g_pkgRing.send.tp_frame_size * g_pkgRing.index));
|
||||
g_pkgRing.index = (g_pkgRing.index + 1) % g_pkgRing.send.tp_frame_nr;
|
||||
|
||||
if (!(hdr->tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING))) {
|
||||
U8 *p = (U8 *)hdr + TPACKET3_HDRLEN - sizeof(struct sockaddr_ll);
|
||||
memcpy(p, pData, nBytes);
|
||||
hdr->tp_next_offset = 0;
|
||||
hdr->tp_len = nBytes;
|
||||
hdr->tp_snaplen = nBytes;
|
||||
hdr->tp_status = TP_STATUS_SEND_REQUEST;
|
||||
return hdr->tp_len;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
|
||||
U16 csum;
|
||||
int tolSize;
|
||||
PDHCP_PACKAGE pRsp = (PDHCP_PACKAGE)malloc(MAX_DHCP_PKG_SIZE);
|
||||
U8 *pOpt = pRsp->dhcp.options;
|
||||
|
||||
|
@ -236,8 +269,10 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
|
|||
|
||||
// IP 头
|
||||
memcpy(&pRsp->vlan_hdr.ip, &pReq->vlan_hdr.ip, sizeof(struct iphdr));
|
||||
// TOS
|
||||
pRsp->vlan_hdr.ip.tos = 0;
|
||||
// 更新源IP
|
||||
pRsp->vlan_hdr.ip.saddr = htonl(g_nicInfo.ipAddr);
|
||||
pRsp->vlan_hdr.ip.saddr = g_nicInfo.ipAddr;
|
||||
// 更新目的IP地址,广播255.255.255.255
|
||||
pRsp->vlan_hdr.ip.daddr = 0xFFFFFFFF;
|
||||
|
||||
|
@ -263,7 +298,10 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
|
|||
// DHCP服务端主机名
|
||||
memcpy(pRsp->dhcp.sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname)));
|
||||
// Magic Cookie: DHCP
|
||||
memcpy(&pRsp->dhcp.cookie, "DHCP", 4);
|
||||
//
|
||||
// memcpy(&pRsp->dhcp.cookie, DHCP_COOKIE_VAL, 4);
|
||||
pRsp->dhcp.cookie = htonl(DHCP_COOKIE_VAL);
|
||||
|
||||
pRsp->dhcp.hops = 0;
|
||||
pRsp->dhcp.secs = 0;
|
||||
pRsp->dhcp.flags = 0;
|
||||
|
@ -273,39 +311,57 @@ static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
|
|||
|
||||
// DHCP Options
|
||||
// DHCP 消息类型
|
||||
dhcp_add_number_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER, 1);
|
||||
pOpt += 3;
|
||||
pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER);
|
||||
// 子网掩码
|
||||
dhcp_add_number_option(pOpt, OPT_NETMASK, pIpInfo->netMask, 4);
|
||||
pOpt += 6;
|
||||
pOpt += dhcp_add_u32_option(pOpt, OPT_NETMASK, htonl(pIpInfo->netMask));
|
||||
// 租约
|
||||
dhcp_add_number_option(pOpt, OPT_IPADDRLEASE, htonl(pIpInfo->leaseTime), 4);
|
||||
pOpt += 6;
|
||||
pOpt += dhcp_add_u32_option(pOpt, OPT_IPADDRLEASE, htonl(pIpInfo->leaseTime));
|
||||
// DHCP Server
|
||||
dhcp_add_number_option(pOpt, OPT_SERVERID, g_nicInfo.ipAddr, 4);
|
||||
pOpt += 6;
|
||||
pOpt += dhcp_add_u32_option(pOpt, OPT_SERVERID, g_nicInfo.ipAddr);
|
||||
// DNS
|
||||
if (pIpInfo->primeDNS != 0) {
|
||||
if (pIpInfo->salveDNS == 0) {
|
||||
dhcp_add_number_option(pOpt, OPT_DNS, pIpInfo->primeDNS, 4);
|
||||
pOpt += 6;
|
||||
pOpt += dhcp_add_u32_option(pOpt, OPT_DNS, htonl(pIpInfo->primeDNS));
|
||||
} else {
|
||||
dhcp_add_buf_option(pOpt, OPT_DNS, (U8 *)&pIpInfo->primeDNS, 8);
|
||||
pOpt += 10;
|
||||
U8 buf[8] = {0};
|
||||
U32 *pVal = (U32 *)buf;
|
||||
*pVal++ = htonl(pIpInfo->primeDNS);
|
||||
*pVal = htonl(pIpInfo->salveDNS);
|
||||
pOpt += dhcp_add_buf_option(pOpt, OPT_DNS, buf, 8);
|
||||
}
|
||||
}
|
||||
// 网关
|
||||
if (pIpInfo->gwAddr != 0) {
|
||||
dhcp_add_number_option(pOpt, OPT_ROUTER, pIpInfo->gwAddr, 4);
|
||||
pOpt += 6;
|
||||
pOpt += dhcp_add_u32_option(pOpt, OPT_ROUTER, htonl(pIpInfo->gwAddr));
|
||||
}
|
||||
// DHCP 主机名
|
||||
dhcp_add_buf_option(pOpt, OPT_DOMAINNAME, (U8 *)g_nicInfo.hostname, strlen(g_nicInfo.hostname));
|
||||
pOpt += strlen(g_nicInfo.hostname) + 2;
|
||||
|
||||
pOpt += dhcp_add_string_option(pOpt, OPT_DOMAINNAME, "workgroup");
|
||||
*pOpt = OPT_END;
|
||||
|
||||
LOG_MSG_HEX(debug, pRsp, 256);
|
||||
// 计算包总长度
|
||||
tolSize = (int)((pOpt - pRsp->dhcp.options) + 1 + sizeof(DHCP_PACKAGE));
|
||||
|
||||
// 计算 IP 数据长度
|
||||
pRsp->vlan_hdr.ip.tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr));
|
||||
// 计算 UDP 数据长度
|
||||
pRsp->vlan_hdr.udp.len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr));
|
||||
|
||||
// 计算 IP 校验和
|
||||
csum = htons(ip_checksum((unsigned char *)&pRsp->vlan_hdr.ip));
|
||||
pRsp->vlan_hdr.ip.check = htons(csum);
|
||||
|
||||
// 计算 UDP 校验和
|
||||
csum = htons(udp_checksum(pRsp->vlan_hdr.ip.saddr, pRsp->vlan_hdr.ip.daddr, (unsigned char *)&pRsp->vlan_hdr.udp));
|
||||
pRsp->vlan_hdr.udp.check = htons(csum);
|
||||
|
||||
LOG_MOD(trace, ZLOG_MOD_DHCPD, "OPTIONS size: %ld\n", (intptr_t)(pOpt - pRsp->dhcp.options) + 1);
|
||||
LOG_MOD(trace, ZLOG_MOD_DHCPD, "Total size: %d\n", tolSize);
|
||||
|
||||
// 发送数据
|
||||
if (pkg_mmap_tx((U8 *)pRsp, tolSize) != tolSize) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Send package(%u bytes) error\n", tolSize);
|
||||
return -ERR_SOCK_SEND;
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
@ -380,8 +436,16 @@ static void on_sock_recv(uv_work_t *req) {
|
|||
u32_to_str_ip(ntohl(ip)));
|
||||
|
||||
ret = dhcp_resp_offer(pkg, pIpInfo, ip);
|
||||
|
||||
if (ret != ERR_SUCCESS) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Send Offer error: %d\n", ret);
|
||||
}
|
||||
} else {
|
||||
//LOG_MOD(error, ZLOG_MOD_DHCPD, );
|
||||
LOG_MOD(error,
|
||||
ZLOG_MOD_DHCPD,
|
||||
"DHCP prepare assign ipaddress error: [%s(%s)]\n",
|
||||
macStr,
|
||||
reqDhcp.hostName);
|
||||
}
|
||||
break;
|
||||
case DHCP_MSG_REQUEST:
|
||||
|
@ -440,8 +504,8 @@ static void after_msg_recv(uv_work_t *req, int status) {
|
|||
void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) {
|
||||
static unsigned int block_num = 0;
|
||||
|
||||
if (status >= 0) {
|
||||
struct block_desc *pbd = (struct block_desc *)g_pkgRing.rd[block_num].iov_base;
|
||||
if (status >= 0 && (events & UV_READABLE)) {
|
||||
struct block_desc *pbd = (struct block_desc *)g_pkgRing.rx[block_num].iov_base;
|
||||
|
||||
if ((pbd->h1.block_status & TP_STATUS_USER) && (pbd->h1.num_pkts > 0)) {
|
||||
int i;
|
||||
|
@ -486,14 +550,14 @@ void raw_sock_recv_cb(uv_poll_t *handle, int status, int events) {
|
|||
}
|
||||
|
||||
static int create_udp_socket() {
|
||||
struct sockaddr_ll addr;
|
||||
unsigned int size;
|
||||
int i;
|
||||
int err;
|
||||
int v = TPACKET_V3;
|
||||
|
||||
struct sockaddr_ll addr;
|
||||
|
||||
// 1. create socket
|
||||
int sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||
int sock_fd = socket(PF_PACKET, SOCK_RAW, 0);
|
||||
if (sock_fd < 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Socket created failure\n");
|
||||
return -ERR_SOCK_CREATE;
|
||||
|
@ -504,73 +568,129 @@ static int create_udp_socket() {
|
|||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Attaching filter failed: %d\n", err);
|
||||
return -ERR_SOCK_SETOPT;
|
||||
}
|
||||
#if 1
|
||||
|
||||
// 3. set PACKET_MMAP version
|
||||
if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_VERSION, &v, sizeof(v))) < 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Set PACKET_VERSION option failed: %d\n", err);
|
||||
return -ERR_SOCK_SETOPT;
|
||||
}
|
||||
|
||||
// 4. setup PAKCET_MMAP ring
|
||||
memset(&g_pkgRing.req, 0, sizeof(g_pkgRing.req));
|
||||
g_pkgRing.req.tp_block_size = PKG_MMAP_BLOCKSIZ;
|
||||
g_pkgRing.req.tp_frame_size = PKG_MMAP_FRAMESIZ;
|
||||
g_pkgRing.req.tp_block_nr = PKG_MMAP_BLOCKNUM;
|
||||
g_pkgRing.req.tp_frame_nr = (PKG_MMAP_BLOCKSIZ * PKG_MMAP_BLOCKNUM) / PKG_MMAP_FRAMESIZ;
|
||||
g_pkgRing.req.tp_retire_blk_tov = 60;
|
||||
g_pkgRing.req.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
|
||||
// 4. setup PAKCET_MMAP rx ring
|
||||
memset(&g_pkgRing.recv, 0, sizeof(g_pkgRing.recv));
|
||||
g_pkgRing.recv.tp_block_size = PKG_MMAP_BLOCKSIZ;
|
||||
g_pkgRing.recv.tp_frame_size = PKG_MMAP_FRAMESIZ;
|
||||
g_pkgRing.recv.tp_block_nr = PKG_MMAP_BLOCKNUM;
|
||||
g_pkgRing.recv.tp_frame_nr = (PKG_MMAP_BLOCKSIZ * PKG_MMAP_BLOCKNUM) / PKG_MMAP_FRAMESIZ;
|
||||
g_pkgRing.recv.tp_retire_blk_tov = 60;
|
||||
g_pkgRing.recv.tp_feature_req_word = TP_FT_REQ_FILL_RXHASH;
|
||||
|
||||
if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_RX_RING, &g_pkgRing.req, sizeof(g_pkgRing.req))) < 0) {
|
||||
if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_RX_RING, &g_pkgRing.recv, sizeof(g_pkgRing.recv))) < 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Set PACKET_RX_RING option failed: %d\n", err);
|
||||
return -ERR_SOCK_SETOPT;
|
||||
}
|
||||
|
||||
g_pkgRing.map = mmap(NULL,
|
||||
g_pkgRing.req.tp_block_size * g_pkgRing.req.tp_block_nr,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_LOCKED,
|
||||
sock_fd,
|
||||
0);
|
||||
// 5. setup PACKET_MMAP tx ring
|
||||
memset(&g_pkgRing.send, 0, sizeof(g_pkgRing.send));
|
||||
g_pkgRing.send.tp_block_size = PKG_MMAP_BLOCKSIZ;
|
||||
g_pkgRing.send.tp_frame_size = PKG_MMAP_FRAMESIZ;
|
||||
g_pkgRing.send.tp_block_nr = PKG_MMAP_BLOCKNUM;
|
||||
g_pkgRing.send.tp_frame_nr = (PKG_MMAP_BLOCKSIZ * PKG_MMAP_BLOCKNUM) / PKG_MMAP_FRAMESIZ;
|
||||
|
||||
if (g_pkgRing.map == MAP_FAILED) {
|
||||
if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_TX_RING, &g_pkgRing.send, sizeof(g_pkgRing.recv))) < 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Set PACKET_TX_RING option failed: %d\n", err);
|
||||
return -ERR_SOCK_SETOPT;
|
||||
}
|
||||
|
||||
// 6. mmap RX/TX ring
|
||||
size = g_pkgRing.recv.tp_block_size * g_pkgRing.recv.tp_block_nr +
|
||||
g_pkgRing.send.tp_block_size * g_pkgRing.send.tp_block_nr;
|
||||
|
||||
g_pkgRing.map_recv = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED | MAP_POPULATE, sock_fd, 0);
|
||||
g_pkgRing.map_send = g_pkgRing.map_recv + g_pkgRing.recv.tp_block_size * g_pkgRing.recv.tp_block_nr;
|
||||
|
||||
if (g_pkgRing.map_recv == MAP_FAILED) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "MMAP socket ring failed\n");
|
||||
perror("title");
|
||||
return -ERR_MMAP_MEMORY;
|
||||
}
|
||||
|
||||
// 5. malloc read buffer
|
||||
g_pkgRing.rd = malloc(g_pkgRing.req.tp_block_nr * sizeof(struct iovec));
|
||||
LOG_MOD(trace, ZLOG_MOD_DHCPD, "size = %u\n", size);
|
||||
LOG_MOD(trace, ZLOG_MOD_DHCPD, "MMAP address recv = %p, send = %p\n", g_pkgRing.map_recv, g_pkgRing.map_send);
|
||||
|
||||
if (g_pkgRing.rd == NULL) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory failed: %lu\n", g_pkgRing.req.tp_block_nr * sizeof(struct iovec));
|
||||
// 7. malloc read buffer
|
||||
g_pkgRing.rx = malloc(g_pkgRing.recv.tp_block_nr * sizeof(struct iovec));
|
||||
if (g_pkgRing.rx == NULL) {
|
||||
LOG_MOD(error,
|
||||
ZLOG_MOD_DHCPD,
|
||||
"Malloc memory failed: %lu\n",
|
||||
g_pkgRing.recv.tp_block_nr * sizeof(struct iovec));
|
||||
return -ERR_MMAP_MEMORY;
|
||||
}
|
||||
|
||||
for (i = 0; i < g_pkgRing.req.tp_block_nr; ++i) {
|
||||
g_pkgRing.rd[i].iov_base = g_pkgRing.map + (i * g_pkgRing.req.tp_block_size);
|
||||
g_pkgRing.rd[i].iov_len = g_pkgRing.req.tp_block_size;
|
||||
memset(g_pkgRing.rx, 0, g_pkgRing.recv.tp_block_nr * sizeof(struct iovec));
|
||||
for (i = 0; i < g_pkgRing.recv.tp_block_nr; ++i) {
|
||||
g_pkgRing.rx[i].iov_base = g_pkgRing.map_recv + (i * g_pkgRing.recv.tp_block_size);
|
||||
g_pkgRing.rx[i].iov_len = g_pkgRing.recv.tp_block_size;
|
||||
}
|
||||
#endif
|
||||
// 6. bind socket
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
// 8. malloc send buffer
|
||||
g_pkgRing.tx = malloc(g_pkgRing.send.tp_block_nr * sizeof(struct iovec));
|
||||
if (g_pkgRing.tx == NULL) {
|
||||
LOG_MOD(error,
|
||||
ZLOG_MOD_DHCPD,
|
||||
"Malloc memory failed: %lu\n",
|
||||
g_pkgRing.send.tp_block_nr * sizeof(struct iovec));
|
||||
|
||||
munmap(g_pkgRing.map_recv, size * 2);
|
||||
return -ERR_MMAP_MEMORY;
|
||||
}
|
||||
|
||||
memset(g_pkgRing.tx, 0, g_pkgRing.send.tp_block_nr * sizeof(struct iovec));
|
||||
for (i = 0; i < g_pkgRing.send.tp_block_nr; ++i) {
|
||||
g_pkgRing.tx[i].iov_base = g_pkgRing.map_send + (i * g_pkgRing.send.tp_block_size);
|
||||
g_pkgRing.tx[i].iov_len = g_pkgRing.send.tp_block_size;
|
||||
}
|
||||
|
||||
// 9. bind socket
|
||||
memset(&addr, 0, sizeof(struct sockaddr_ll));
|
||||
addr.sll_ifindex = (int)if_nametoindex(g_nicInfo.pIfName);
|
||||
addr.sll_family = AF_PACKET;
|
||||
addr.sll_family = PF_PACKET;
|
||||
addr.sll_protocol = htons(ETH_P_ALL);
|
||||
addr.sll_hatype = 0;
|
||||
addr.sll_pkttype = 0;
|
||||
addr.sll_halen = 0;
|
||||
|
||||
if ((err = bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
|
||||
if ((err = bind(sock_fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_ll))) < 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Bind raw socket failed: %d\n", err);
|
||||
return -ERR_SOCK_SETOPT;
|
||||
}
|
||||
|
||||
return sock_fd;
|
||||
g_pkgRing.sock = sock_fd;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static void socket_send_task(uv_timer_t *UNUSED(pArg)) {
|
||||
int i;
|
||||
struct tpacket3_hdr *hdr;
|
||||
|
||||
for (i = 0; i < g_pkgRing.send.tp_frame_nr && g_pkgRing.sock != 0; i++) {
|
||||
hdr = (struct tpacket3_hdr *)(g_pkgRing.tx[0].iov_base + (g_pkgRing.send.tp_frame_size * i));
|
||||
if ((hdr->tp_status & TP_STATUS_SEND_REQUEST) || (hdr->tp_status & TP_STATUS_SENDING)) {
|
||||
ssize_t ret = sendto(g_pkgRing.sock, NULL, 0, MSG_DONTWAIT, NULL, sizeof(struct sockaddr_ll));
|
||||
|
||||
if (ret == -1) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Send pakcet error\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int dhcpd_init() {
|
||||
static uv_udp_t uvRaw;
|
||||
static uv_poll_t uvSocket;
|
||||
int sock;
|
||||
static uv_timer_t uvTm;
|
||||
int ret;
|
||||
size_t size = MAX_PATH;
|
||||
|
||||
memset(&g_nicInfo, 0, sizeof(NIC_INFO));
|
||||
|
@ -579,21 +699,24 @@ int dhcpd_init() {
|
|||
|
||||
get_nic_info(g_nicInfo.pIfName, &g_nicInfo.ipAddr, &g_nicInfo.netmask, NULL, g_nicInfo.macAddr);
|
||||
|
||||
sock = create_udp_socket();
|
||||
|
||||
if (sock <= 0) {
|
||||
return sock;
|
||||
ret = create_udp_socket();
|
||||
if (ret != ERR_SUCCESS) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Create receive RAW Socket Error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dhcp_user_mgr_init();
|
||||
dhcp_option_cfg_init();
|
||||
dhcp_lease_init();
|
||||
|
||||
uv_udp_init(get_task_manager(), &uvRaw);
|
||||
uv_udp_open(&uvRaw, sock);
|
||||
uv_udp_init(get_task_manager(), &g_uvRawScokReq);
|
||||
uv_udp_open(&g_uvRawScokReq, g_pkgRing.sock);
|
||||
|
||||
uv_poll_init_socket(get_task_manager(), &uvSocket, sock);
|
||||
uv_poll_init_socket(get_task_manager(), &uvSocket, g_pkgRing.sock);
|
||||
uv_poll_start(&uvSocket, UV_READABLE, raw_sock_recv_cb);
|
||||
|
||||
uv_timer_init(get_task_manager(), &uvTm);
|
||||
uv_timer_start(&uvTm, socket_send_task, 3000, 100);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
|
@ -141,8 +141,10 @@ typedef struct {
|
|||
U8 len;
|
||||
} DHCP_OPT, *PDHCP_OPT;
|
||||
|
||||
void dhcp_add_number_option(U8 *pBegin, int opt, U8 value, U8 nSize);
|
||||
void dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize);
|
||||
int dhcp_add_u8_option(U8 *pBegin, int opt, U8 value);
|
||||
int dhcp_add_u32_option(U8 *pBegin, int opt, U32 value);
|
||||
int dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize);
|
||||
int dhcp_add_string_option(U8 *pBegin, int opt, const char *buf);
|
||||
int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal);
|
||||
void dhcp_option_cfg_init();
|
||||
#ifdef __cplusplus
|
||||
|
|
Loading…
Reference in New Issue