// // Created by xajhuang on 2023/4/20. // #include #include #include #include "user_errno.h" #include "dhcp_network.h" #include "dhcp_options.h" #include "zlog_module.h" #include "main.h" #include "rfc2131.h" #include "misc.h" static char *g_pNicName = NULL; static struct sock_filter g_filterCode[] = { // 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 struct sock_fprog bpf = { .len = sizeof(g_filterCode) / (sizeof(struct sock_filter)), .filter = g_filterCode, }; U8 *dhcp_create_discover_req(PDHCP_INFO pInfo, int *pOutSize) { static U8 reqParams[] = {0x01, 0x1c, 0x02, 0x03, 0x0f, 0x06, 0x77, 0x0c, 0x2c, 0x2f, 0x1a, 0x79, 0x2a}; U8 *pOpt; U16 csum; int tolSize; U8 *pReqData = (U8 *)malloc(MAX_DHCP_PKG_SIZE); if (pReqData) { PDHCP_PACKAGE p = (PDHCP_PACKAGE)pReqData; memset(pReqData, 0, MAX_DHCP_PKG_SIZE); // 目的地 MAC 地址 memset(p->vlan_hdr.eth.h_dest, 0xFF, ETH_ALEN); // 源 MAC 地址 memcpy(p->vlan_hdr.eth.h_source, pInfo->mac, ETH_ALEN); // 协议 VLAN p->vlan_hdr.eth.h_proto = htons(ETH_P_8021Q); // VLAN 隧道信息 p->vlan_hdr.vlan.id = htons(pInfo->vni); p->vlan_hdr.vlan.type = htons(ETH_P_IP); // IP 头 p->vlan_hdr.ip.version = IPVERSION; p->vlan_hdr.ip.ihl = 5; p->vlan_hdr.ip.tos = 0x10; p->vlan_hdr.ip.tot_len = 0; p->vlan_hdr.ip.id = 0; p->vlan_hdr.ip.frag_off = 0; p->vlan_hdr.ip.ttl = 128; p->vlan_hdr.ip.protocol = IPPROTO_UDP; p->vlan_hdr.ip.check = 0; p->vlan_hdr.ip.saddr = INADDR_ANY; p->vlan_hdr.ip.daddr = INADDR_BROADCAST; // UDP 头 p->vlan_hdr.udp.source = htons(DHCP_CLI_PORT); p->vlan_hdr.udp.dest = htons(DHCP_SVR_PORT); p->vlan_hdr.udp.len = 0; p->vlan_hdr.udp.check = 0; // DHCP 协议内容 p->dhcp.op = BOOTP_REQUEST; p->dhcp.htype = 0x01; p->dhcp.hlen = ETH_ALEN; p->dhcp.hops = 0; p->dhcp.xid = htonl(rand_number()); p->dhcp.secs = 0; p->dhcp.flags = 0; p->dhcp.ciaddr = INADDR_ANY; p->dhcp.yiaddr = INADDR_ANY; p->dhcp.siaddr = INADDR_ANY; p->dhcp.giaddr = INADDR_ANY; memcpy(p->dhcp.chaddr, pInfo->mac, ETH_ALEN); p->dhcp.cookie = htonl(DHCP_COOKIE_VAL); // DHCP Options pOpt = p->dhcp.options; // DHCP 消息类型 pOpt += dhcp_add_u8_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_DISCOVER); // DHCP 主机名 pOpt += dhcp_add_string_option(pOpt, OPT_HOSTNAME, pInfo->hostname); // DHCP 请求参数列表 pOpt += dhcp_add_buf_option(pOpt, OPT_PARAMREQLIST, reqParams, 13); // 结束 *pOpt = OPT_END; // 计算包总长度 tolSize = (int)((pOpt - p->dhcp.options) + 1 + sizeof(DHCP_PACKAGE)); // 计算 IP 数据长度 p->vlan_hdr.ip.tot_len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr)); // 计算 UDP 数据长度 p->vlan_hdr.udp.len = htons(tolSize - sizeof(struct ethhdr) - sizeof(struct vlan_hdr) - sizeof(struct iphdr)); // 计算 IP 校验和 csum = htons(ip_checksum((unsigned char *)&p->vlan_hdr.ip)); p->vlan_hdr.ip.check = htons(csum); // 计算 UDP 校验和 csum = htons(udp_checksum(p->vlan_hdr.ip.saddr, p->vlan_hdr.ip.daddr, (unsigned char *)&p->vlan_hdr.udp)); p->vlan_hdr.udp.check = htons(csum); *pOutSize = tolSize; } return pReqData; } static void on_dhcp_recv(uv_work_t *req) { printf("+++++++++++++recv\n"); //LOG_MOD_HEX(debug, ZLOG_MOD_MAIN, dhcp_create_discover_req(&info), 512); } int dhcp_tools_init_network(const char *pNicName) { static RECV_CB_DATA rcData; static uv_poll_t uvSocket; static uv_timer_t uvTm; int ret; if (g_pNicName == NULL) { g_pNicName = strdup(pNicName); } else if (strcmp(pNicName, g_pNicName) != 0) { dhcp_uninit(); free(g_pNicName); g_pNicName = strdup(pNicName); } else { return ERR_SUCCESS; } init_filter("vlan and udp and port 67 and port 68"); ret = create_udp_raw_socket(g_pNicName); if (ret != ERR_SUCCESS) { LOG_MOD(error, ZLOG_MOD_DHCPD, "Create receive RAW Socket Error: %s(%d)\n", getErrorEnumNameString(-ret), ret); return ret; } dhcp_option_cfg_init(); init_raw_socket_poll(on_dhcp_recv, NULL); return ERR_SUCCESS; }