vcpe/srcs/service/dhcpd/dhcpd_network.c

599 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by xajhuang on 2023/3/16.
//
#include <uv.h>
#include <stdlib.h>
#include <string.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include "service/dhcpd.h"
#include "user_errno.h"
#include "task_manager.h"
#include "zlog_module.h"
#include "network/vlan.h"
#include "dhcp_options.h"
#include "config.h"
#include "misc.h"
#include "user_mgr.h"
#define PKG_MMAP_BLOCKSIZ (1 << 22)
#define PKG_MMAP_FRAMESIZ (1 << 11)
#define PKG_MMAP_BLOCKNUM (64)
#define MAX_DHCP_PKG_SIZE (512)
#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;
U8 cliMac[ETH_ALEN];
U32 xid;
U32 reqIpAddr;
U32 leaseTime;
char clientId[256];
char vendorClassId[256];
char hostName[256];
} DHCP_REQ, *PDHCP_REQ;
typedef struct {
struct iovec *rd;
uint8_t *map;
struct tpacket_req3 req;
} PACKET_MMAP_RING, *PPACKET_MMAP_RING;
typedef struct {
char *pIfName;
U32 ipAddr;
U32 netmask;
U8 macAddr[ETH_ALEN];
S8 hostname[MAX_PATH];
} NIC_INFO, *PNIC_INFO;
struct block_desc {
uint32_t version;
uint32_t offset_to_priv;
struct tpacket_hdr_v1 h1;
};
#pragma pack(1)
typedef struct {
VLAN_PKG_HDR vlan_hdr;
DHCP_PROTO dhcp;
} DHCP_PACKAGE, *PDHCP_PACKAGE;
typedef struct {
uv_work_t uvWork;
unsigned short nSize;
unsigned char *pPkgBase;
void *pData;
} PKG_PROCESS_INFO, *PPKG_PROCESS_INFO;
typedef struct {
unsigned int nf;
PPKG_PROCESS_INFO pPkgInfo;
} PKG_MSG, *PPKG_MSG;
#pragma pack()
/*
TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are
responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT
messages) originating within their racks to anycast VIPs, one DHCPv4 and one
for DHCPv6.
*/
static struct sock_filter g_filterCode[] = {
#ifdef UDP_DHCP_FILTER
// create by: tcpdump "udp and port 67 and port 68" -dd
{0x28, 0, 0, 0x0000000c},
{0x15, 0, 9, 0x000086dd},
{0x30, 0, 0, 0x00000014},
{0x15, 0, 21, 0x00000011},
{0x28, 0, 0, 0x00000036},
{0x15, 0, 2, 0x00000043},
{0x28, 0, 0, 0x00000038},
{0x15, 16, 17, 0x00000044},
{0x15, 0, 16, 0x00000044},
{0x28, 0, 0, 0x00000038},
{0x15, 13, 14, 0x00000043},
{0x15, 0, 13, 0x00000800},
{0x30, 0, 0, 0x00000017},
{0x15, 0, 11, 0x00000011},
{0x28, 0, 0, 0x00000014},
{0x45, 9, 0, 0x00001fff},
{0xb1, 0, 0, 0x0000000e},
{0x48, 0, 0, 0x0000000e},
{0x15, 0, 2, 0x00000043},
{0x48, 0, 0, 0x00000010},
{0x15, 3, 4, 0x00000044},
{0x15, 0, 3, 0x00000044},
{0x48, 0, 0, 0x00000010},
{0x15, 0, 1, 0x00000043},
{0x6, 0, 0, 0x00040000},
{0x6, 0, 0, 0x00000000},
#endif
#if 0
// create by: tcpdump "vxlan" -dd
{0x28, 0, 0, 0x0000000c},
{0x15, 2, 0, 0x00008100},
{0x15, 1, 0, 0x000088a8},
{0x15, 0, 1, 0x00009100},
{0x6, 0, 0, 0x00040000},
{0x6, 0, 0, 0x00000000},
#endif
// region BPF code
// create by: tcpdump "vlan and udp and port 67 and port 68" -dd
{0x0, 0, 0, 0x00000000},
{0x2, 0, 0, 0x00000000},
{0x2, 0, 0, 0x00000001},
{0x30, 0, 0, 0xfffff030},
{0x15, 7, 0, 0x00000001},
{0x0, 0, 0, 0x00000004},
{0x2, 0, 0, 0x00000000},
{0x2, 0, 0, 0x00000001},
{0x28, 0, 0, 0x0000000c},
{0x15, 2, 0, 0x00008100},
{0x15, 1, 0, 0x000088a8},
{0x15, 0, 56, 0x00009100},
{0x61, 0, 0, 0x00000001},
{0x48, 0, 0, 0x0000000c},
{0x15, 0, 13, 0x000086dd},
{0x61, 0, 0, 0x00000000},
{0x50, 0, 0, 0x00000014},
{0x15, 0, 50, 0x00000011},
{0x61, 0, 0, 0x00000000},
{0x48, 0, 0, 0x00000036},
{0x15, 0, 3, 0x00000043},
{0x61, 0, 0, 0x00000000},
{0x48, 0, 0, 0x00000038},
{0x15, 43, 44, 0x00000044},
{0x15, 0, 43, 0x00000044},
{0x61, 0, 0, 0x00000000},
{0x48, 0, 0, 0x00000038},
{0x15, 39, 40, 0x00000043},
{0x15, 0, 39, 0x00000800},
{0x61, 0, 0, 0x00000000},
{0x50, 0, 0, 0x00000017},
{0x15, 0, 36, 0x00000011},
{0x61, 0, 0, 0x00000000},
{0x48, 0, 0, 0x00000014},
{0x45, 33, 0, 0x00001fff},
{0x61, 0, 0, 0x00000000},
{0x50, 0, 0, 0x0000000e},
{0x54, 0, 0, 0x0000000f},
{0x64, 0, 0, 0x00000002},
{0xc, 0, 0, 0x00000000},
{0x7, 0, 0, 0x00000000},
{0x48, 0, 0, 0x0000000e},
{0x15, 0, 8, 0x00000043},
{0x61, 0, 0, 0x00000000},
{0x50, 0, 0, 0x0000000e},
{0x54, 0, 0, 0x0000000f},
{0x64, 0, 0, 0x00000002},
{0xc, 0, 0, 0x00000000},
{0x7, 0, 0, 0x00000000},
{0x48, 0, 0, 0x00000010},
{0x15, 16, 17, 0x00000044},
{0x61, 0, 0, 0x00000000},
{0x50, 0, 0, 0x0000000e},
{0x54, 0, 0, 0x0000000f},
{0x64, 0, 0, 0x00000002},
{0xc, 0, 0, 0x00000000},
{0x7, 0, 0, 0x00000000},
{0x48, 0, 0, 0x0000000e},
{0x15, 0, 9, 0x00000044},
{0x61, 0, 0, 0x00000000},
{0x50, 0, 0, 0x0000000e},
{0x54, 0, 0, 0x0000000f},
{0x64, 0, 0, 0x00000002},
{0xc, 0, 0, 0x00000000},
{0x7, 0, 0, 0x00000000},
{0x48, 0, 0, 0x00000010},
{0x15, 0, 1, 0x00000043},
{0x6, 0, 0, 0x00040000},
{0x6, 0, 0, 0x00000000},
// endregion
};
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 struct sock_fprog bpf = {
.len = sizeof(g_filterCode) / (sizeof(struct sock_filter)),
.filter = g_filterCode,
};
static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
PDHCP_PACKAGE pRsp = (PDHCP_PACKAGE)malloc(MAX_DHCP_PKG_SIZE);
U8 *pOpt = pRsp->dhcp.options;
if (pRsp == NULL) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
return -ERR_MALLOC_MEMORY;
}
memset(pRsp, 0, MAX_DHCP_PKG_SIZE);
// 二层头
// 目的IP地址
memset(pRsp->vlan_hdr.eth.h_dest, 0xFF, ETH_ALEN);
// 源 IP 地址
memcpy(pRsp->vlan_hdr.eth.h_source, g_nicInfo.macAddr, ETH_ALEN);
// protol
pRsp->vlan_hdr.eth.h_proto = pReq->vlan_hdr.eth.h_proto;
// QinQ 隧道
pRsp->vlan_hdr.vlan.id = pReq->vlan_hdr.vlan.id;
pRsp->vlan_hdr.vlan.type = pReq->vlan_hdr.vlan.type;
// TODO 可能的二层QinQ隧道
// IP 头
memcpy(&pRsp->vlan_hdr.ip, &pReq->vlan_hdr.ip, sizeof(struct iphdr));
// 更新源IP
pRsp->vlan_hdr.ip.saddr = htonl(g_nicInfo.ipAddr);
// 更新目的IP地址广播255.255.255.255
pRsp->vlan_hdr.ip.daddr = 0xFFFFFFFF;
// UDP 头
// 目的端口
pRsp->vlan_hdr.udp.dest = pReq->vlan_hdr.udp.source;
// 源端口
pRsp->vlan_hdr.udp.source = pReq->vlan_hdr.udp.dest;
//DHCP 协议
// 返回类型
pRsp->dhcp.op = BOOTP_REPLY;
// 地址类型长度
pRsp->dhcp.htype = pReq->dhcp.htype;
// 地址长度
pRsp->dhcp.hlen = pReq->dhcp.hlen;
// xid
pRsp->dhcp.xid = pReq->dhcp.xid;
// 分配的 IP 地址
pRsp->dhcp.yiaddr = htonl(ip);
// 客户端 MAC 地址
memcpy(pRsp->dhcp.chaddr, pReq->dhcp.chaddr, ETH_ALEN);
// DHCP服务端主机名
memcpy(pRsp->dhcp.sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname)));
// Magic Cookie: DHCP
memcpy(&pRsp->dhcp.cookie, "DHCP", 4);
pRsp->dhcp.hops = 0;
pRsp->dhcp.secs = 0;
pRsp->dhcp.flags = 0;
pRsp->dhcp.ciaddr = 0;
pRsp->dhcp.siaddr = 0;
pRsp->dhcp.giaddr = 0;
// DHCP Options
// DHCP 消息类型
dhcp_add_number_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER, 1);
pOpt += 3;
// 子网掩码
dhcp_add_number_option(pOpt, OPT_NETMASK, pIpInfo->netMask, 4);
pOpt += 6;
// 租约
dhcp_add_number_option(pOpt, OPT_IPADDRLEASE, htonl(pIpInfo->leaseTime), 4);
pOpt += 6;
// DHCP Server
dhcp_add_number_option(pOpt, OPT_SERVERID, g_nicInfo.ipAddr, 4);
pOpt += 6;
// DNS
if (pIpInfo->primeDNS != 0) {
if (pIpInfo->salveDNS == 0) {
dhcp_add_number_option(pOpt, OPT_DNS, pIpInfo->primeDNS, 4);
pOpt += 6;
} else {
dhcp_add_buf_option(pOpt, OPT_DNS, (U8 *)&pIpInfo->primeDNS, 8);
pOpt += 10;
}
}
// 网关
if (pIpInfo->gwAddr != 0) {
dhcp_add_number_option(pOpt, OPT_ROUTER, pIpInfo->gwAddr, 4);
pOpt += 6;
}
// DHCP 主机名
dhcp_add_buf_option(pOpt, OPT_DOMAINNAME, (U8 *)g_nicInfo.hostname, strlen(g_nicInfo.hostname));
pOpt += strlen(g_nicInfo.hostname) + 2;
*pOpt = OPT_END;
LOG_MSG_HEX(debug, pRsp, 256);
return ERR_SUCCESS;
}
static void on_sock_recv(uv_work_t *req) {
char macStr[20] = {0};
U32 ip;
PIPPOOL_INFO pIpInfo;
DHCP_REQ reqDhcp;
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);
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, ZLOG_MOD_DHCPD, "Error message op code %d\n", pkg->dhcp.op);
return;
}
// 获取消息类型
ret = dhcp_get_option(OPT_MESSAGETYPE, pkg->dhcp.options, optSize, &optMsg);
if (ret != ERR_SUCCESS) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "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);
memcpy(reqDhcp.cliMac, pkg->dhcp.chaddr, ETH_ALEN);
switch (*optMsg.pValue) {
case DHCP_MSG_DISCOVER:
ret = dhcp_get_option(OPT_REQUESTEDIPADDR, pkg->dhcp.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);
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);
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);
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);
if (ret == ERR_SUCCESS) {
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256));
}
MAC_TO_STR(reqDhcp.cliMac, macStr);
ret = pre_alloc_dhcp_res(VLAN_VNI_ID(pkg->vlan_hdr.vlan.id), macStr, &ip, &pIpInfo);
if (ret == ERR_SUCCESS) {
LOG_MOD(trace,
ZLOG_MOD_DHCPD,
"DHCP prepare assign ipaddress: [%s(%s)] --> %s\n",
macStr,
reqDhcp.hostName,
u32_to_str_ip(ntohl(ip)));
ret = dhcp_resp_offer(pkg, pIpInfo, ip);
} else {
//LOG_MOD(error, ZLOG_MOD_DHCPD, );
}
break;
case DHCP_MSG_REQUEST:
break;
case DHCP_MSG_RELEASE:
break;
case DHCP_MSG_INFORM:
break;
case DHCP_MSG_DECLINE:
break;
default:
LOG_MOD(error, ZLOG_MOD_DHCPD, "Unkonwn DHCP message type: %d\n", *optMsg.pValue);
LOG_MSG_HEX(trace, pkg, pWork->nSize);
break;
}
//dhcp_option_prase(optMsg, pkg->dhcp.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->vlan_hdr.vlan.id), DHCP_XID(pkg->dhcp.xid));
#if 0
LOG_MOD(info, ZLOG_MOD_DHCPD, "vlan = %u\n", VXLAN_VIN_ID_PACK(pkg->vlan_hdr.vlan.id));
LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid));
LOG_MSG(info,
"dest mac: %02X:%02X:%02X:%02X:%02X:%02X\n",
pkg->vlan_hdr.eth.h_dest[0],
pkg->vlan_hdr.eth.h_dest[1],
pkg->vlan_hdr.eth.h_dest[2],
pkg->vlan_hdr.eth.h_dest[3],
pkg->vlan_hdr.eth.h_dest[4],
pkg->vlan_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]);
#endif
}
static void after_msg_recv(uv_work_t *req, int status) {
PPKG_PROCESS_INFO pInfo = (PPKG_PROCESS_INFO)req->data;
PPKG_MSG pMsg = (PPKG_MSG)pInfo->pData;
pMsg->nf -= 1;
if (pMsg->nf == 0) {
LOG_MOD(trace, ZLOG_MOD_DHCPD, "---Free resources: %p\n", pMsg);
free(pMsg->pPkgInfo);
free(pMsg);
}
}
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 ((pbd->h1.block_status & TP_STATUS_USER) && (pbd->h1.num_pkts > 0)) {
int i;
struct tpacket3_hdr *ppd;
unsigned int memSize = sizeof(PKG_PROCESS_INFO) * pbd->h1.num_pkts;
PPKG_MSG pMsg = (PPKG_MSG)malloc(sizeof(PKG_MSG));
if (pMsg == NULL) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %lu\n", sizeof(PKG_MSG));
return;
}
LOG_MOD(trace, ZLOG_MOD_DHCPD, "++++Malloc resources: %p\n", pMsg);
memset(pMsg, 0, sizeof(PKG_MSG));
pMsg->pPkgInfo = (PPKG_PROCESS_INFO)malloc(memSize);
if (pMsg->pPkgInfo == NULL) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %u\n", memSize);
free(pMsg);
return;
}
memset(pMsg->pPkgInfo, 0, memSize);
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++) {
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;
uv_queue_work(get_task_manager(), &(pMsg->pPkgInfo[i].uvWork), on_sock_recv, after_msg_recv);
ppd = (struct tpacket3_hdr *)((uint8_t *)ppd + ppd->tp_next_offset);
}
}
pbd->h1.block_status = TP_STATUS_KERNEL;
block_num = (block_num + 1) % PKG_MMAP_BLOCKNUM;
}
}
static int create_udp_socket() {
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));
if (sock_fd < 0) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Socket created failure\n");
return -ERR_SOCK_CREATE;
}
// 2. attach filter (no need to call bind)
if ((err = setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))) < 0) {
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;
if ((err = setsockopt(sock_fd, SOL_PACKET, PACKET_RX_RING, &g_pkgRing.req, sizeof(g_pkgRing.req))) < 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);
if (g_pkgRing.map == MAP_FAILED) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "MMAP socket ring failed\n");
return -ERR_MMAP_MEMORY;
}
// 5. malloc read buffer
g_pkgRing.rd = malloc(g_pkgRing.req.tp_block_nr * sizeof(struct iovec));
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));
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;
}
#endif
// 6. bind socket
memset(&addr, 0, sizeof(addr));
addr.sll_ifindex = (int)if_nametoindex(g_nicInfo.pIfName);
addr.sll_family = AF_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) {
LOG_MOD(error, ZLOG_MOD_DHCPD, "Bind raw socket failed: %d\n", err);
return -ERR_SOCK_SETOPT;
}
return sock_fd;
}
int dhcpd_init() {
static uv_udp_t uvRaw;
static uv_poll_t uvSocket;
int sock;
size_t size = MAX_PATH;
memset(&g_nicInfo, 0, sizeof(NIC_INFO));
g_nicInfo.pIfName = (char *)config_get_dhcp_nic_name();
uv_os_gethostname(g_nicInfo.hostname, &size);
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;
}
dhcp_user_mgr_init();
dhcp_option_cfg_init();
dhcp_lease_init();
uv_udp_init(get_task_manager(), &uvRaw);
uv_udp_open(&uvRaw, sock);
uv_poll_init_socket(get_task_manager(), &uvSocket, sock);
uv_poll_start(&uvSocket, UV_READABLE, raw_sock_recv_cb);
return ERR_SUCCESS;
}