OCT 1. 添加dhcp协议解析基本
This commit is contained in:
parent
86c4f8c68d
commit
b36960f878
|
@ -0,0 +1,105 @@
|
||||||
|
//
|
||||||
|
// Created by xajhuang on 2023/3/16.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef VCPE_DHCPD_H
|
||||||
|
#define VCPE_DHCPD_H
|
||||||
|
#include <common.h>
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma pack(push)
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| op (1) | htype (1) | hlen (1) | hops (1) |
|
||||||
|
+---------------+---------------+---------------+---------------+
|
||||||
|
| xid (4) |
|
||||||
|
+-------------------------------+-------------------------------+
|
||||||
|
| secs (2) | flags (2) |
|
||||||
|
+-------------------------------+-------------------------------+
|
||||||
|
| ciaddr (4) |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| yiaddr (4) |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| siaddr (4) |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| giaddr (4) |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
| chaddr (16) |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
| sname (64) |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
| file (128) |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
| |
|
||||||
|
| options (variable) |
|
||||||
|
+---------------------------------------------------------------+
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
///< 报文的操作类型。分为请求报文和响应报文。1:请求报文,2:应答报文。即client送给server的封包,设为1,反之为2
|
||||||
|
U8 op;
|
||||||
|
///< DHCP客户端的MAC地址类型。MAC地址类型其实是指明网络类型。htype值为1时表示为最常见的以太网MAC地址类型
|
||||||
|
U8 htype;
|
||||||
|
///< DHCP客户端的MAC地址长度。以太网MAC地址长度为6个字节,即以太网时hlen值为6
|
||||||
|
U8 hlen;
|
||||||
|
///< DHCP报文经过的DHCP中继的数目,默认为0。DHCP请求报文每经过一个DHCP中继,该字段就会增加1。没有经过DHCP中继时值为0
|
||||||
|
U8 hops;
|
||||||
|
///< 客户端通过DHCP Discover报文发起一次IP地址请求时选择的随机数,相当于请求标识。用来标识一次IP地址请求过程。在一次请求中所有报文的Xid都是一样的
|
||||||
|
U32 xid;
|
||||||
|
///< DHCP客户端从获取到IP地址或者续约过程开始到现在所消耗的时间,以秒为单位。
|
||||||
|
///< 在没有获得IP地址前该字段始终为0(DHCP客户端开始DHCP请求后所经过的时间。目前尚未使用,固定为0)
|
||||||
|
U16 secs;
|
||||||
|
///< 标志位,只使用第0比特位,是广播应答标识位,用来标识DHCP服务器应答报文是采用单播还是广播发送,
|
||||||
|
///< 0表示采用单播发送方式,1表示采用广播发送方式。其余位尚未使用。(即从0-15bits,最左1bit为1时表示server将以广播方式传送封包给client。)
|
||||||
|
U16 flags;
|
||||||
|
///< DHCP客户端的IP地址。仅在DHCP服务器发送的ACK报文中显示,因为在得到DHCP服务器确认前,DHCP客户端是还没有分配到IP地址的。
|
||||||
|
///< 在其他报文中均显示,只有客户端是Bound、Renew、Rebinding状态,并且能响应ARP请求时,才能被填充
|
||||||
|
U32 ciaddr;
|
||||||
|
///< DHCP服务器分配给客户端的IP地址。仅在DHCP服务器发送的Offer和ACK报文中显示,其他报文中显示为0
|
||||||
|
U32 yiaddr;
|
||||||
|
///< 下一个为DHCP客户端分配IP地址等信息的DHCP服务器IP地址。仅在DHCP Offer、DHCP ACK报文中显示,其他报文中显示为0
|
||||||
|
U32 siaddr;
|
||||||
|
///< DHCP客户端发出请求报文后经过的第一个DHCP中继的IP地址。如果没有经过DHCP中继,则显示为0。(转发代理(网关)IP地址)
|
||||||
|
U32 giaddr;
|
||||||
|
///< DHCP客户端的MAC地址。在每个报文中都会显示对应DHCP客户端的MAC地址
|
||||||
|
U8 chaddr[16];
|
||||||
|
///< 为DHCP客户端分配IP地址的DHCP服务器名称(DNS域名格式)。在Offer和ACK报文中显示发送报文的DHCP服务器名称,其他报文显示为0
|
||||||
|
U8 sname[64];
|
||||||
|
///< DHCP服务器为DHCP客户端指定的启动配置文件名称及路径信息。仅在DHCP Offer报文中显示,其他报文中显示为空
|
||||||
|
U8 file[128];
|
||||||
|
///< 可选项字段,长度可变,格式为"代码+长度+数据"
|
||||||
|
U8 options[0];
|
||||||
|
} DHCP_PROTO, *PDHCP_PROTO;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
U8 flags;
|
||||||
|
U8 res1;
|
||||||
|
U8 res2;
|
||||||
|
U8 res3;
|
||||||
|
U32 vni;
|
||||||
|
} VXLAN_HDR, *PVXLAN_HDR;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
U16 out_priority_cfi_and_id;
|
||||||
|
U16 in_type;
|
||||||
|
U16 in_priority_cfi_and_id;
|
||||||
|
U16 origin_type;
|
||||||
|
} QINQ_HDR, *PQINQ_HDR;
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
int dhcpd_init();
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif //VCPE_DHCPD_H
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
INCLUDE_DIRECTORIES(. ../include ../libs/include)
|
||||||
|
|
||||||
|
AUX_SOURCE_DIRECTORY(dhcpd DHCPD_SRC)
|
||||||
|
|
||||||
|
ADD_LIBRARY(dhcpd ${DHCPD_SRC} ${DHCPD_HEADS})
|
|
@ -0,0 +1,185 @@
|
||||||
|
//
|
||||||
|
// Created by xajhuang on 2023/3/16.
|
||||||
|
//
|
||||||
|
#include <uv.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <linux/filter.h>
|
||||||
|
#include <linux/if_ether.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/udp.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
|
||||||
|
#include "service/dhcpd.h"
|
||||||
|
#include "user_errno.h"
|
||||||
|
#include "task_manager.h"
|
||||||
|
#include "zlog_module.h"
|
||||||
|
|
||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct ethhdr eth;
|
||||||
|
struct iphdr ip;
|
||||||
|
struct udphdr udp;
|
||||||
|
DHCP_PROTO dhcp;
|
||||||
|
} DHCP_PACKAGE, *PDHCP_PACKAGE;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int vni;
|
||||||
|
unsigned short q1;
|
||||||
|
unsigned short q2;
|
||||||
|
} VXLAN_TAG, *PVXLAN_TAG;
|
||||||
|
|
||||||
|
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
|
||||||
|
// 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},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sock_fprog bpf = {
|
||||||
|
.len = sizeof(g_filterCode) / (sizeof(struct sock_filter)),
|
||||||
|
.filter = g_filterCode,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
|
||||||
|
*buf = uv_buf_init(malloc(suggested_size), suggested_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void package_process(uv_work_t *req) {
|
||||||
|
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)req->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_read(uv_udp_t *req, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags) {
|
||||||
|
if (nread > 0) {
|
||||||
|
uv_work_t *pWork = (uv_work_t *)malloc(sizeof(uv_work_t));
|
||||||
|
|
||||||
|
if (!pWork) {
|
||||||
|
free(buf->base);
|
||||||
|
LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Malloc %lu memory error\n", sizeof(uv_work_t));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pWork->data = (void *)buf;
|
||||||
|
uv_queue_work(get_task_manager(), pWork, package_process, NULL);
|
||||||
|
|
||||||
|
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)buf->base;
|
||||||
|
LOG_MSG(info, "xid: 0x%08X\n", ntohl(pkg->dhcp.xid));
|
||||||
|
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]);
|
||||||
|
//LOG_MSG_HEX(debug, buf->base, nread);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int create_udp_socket() {
|
||||||
|
struct sockaddr_ll addr;
|
||||||
|
|
||||||
|
// 1. create socket
|
||||||
|
int sock_fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
||||||
|
if (sock_fd < 0) {
|
||||||
|
perror("socket created failure");
|
||||||
|
return -ERR_SOCK_CREATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *iface_name = "ens192";
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sll_ifindex = (int)if_nametoindex(iface_name);
|
||||||
|
addr.sll_family = AF_PACKET;
|
||||||
|
addr.sll_protocol = htons(ETH_P_ALL);
|
||||||
|
|
||||||
|
// 2. attach filter (no need to call bind)
|
||||||
|
if (setsockopt(sock_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf)) < 0) {
|
||||||
|
perror("attaching filter failed");
|
||||||
|
return -ERR_SOCK_SETOPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define MAX_DATE_ITEMS (64)
|
||||||
|
|
||||||
|
void fib(uv_work_t *req) {
|
||||||
|
int cnt = 3;
|
||||||
|
fprintf(stderr, "Task %ld\n", (long)(req->data));
|
||||||
|
while (cnt--) {
|
||||||
|
uv_sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void after_fib(uv_work_t *req, int status) {
|
||||||
|
fprintf(stderr, "Finish Task %ld\n", (long)(req->data));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
int dhcpd_init() {
|
||||||
|
static uv_udp_t uvRaw;
|
||||||
|
#if 0
|
||||||
|
static unsigned int data[MAX_DATE_ITEMS];
|
||||||
|
static uv_work_t req[MAX_DATE_ITEMS];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_DATE_ITEMS; i++) {
|
||||||
|
req[i].data = (void *)(intptr_t)i;
|
||||||
|
uv_queue_work(get_task_manager(), &req[i], fib, after_fib);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int sock = create_udp_socket();
|
||||||
|
|
||||||
|
if (sock <= 0) {
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_MSG(info, "sizeof DHCP_PACKAGE = %lu\n", sizeof(DHCP_PACKAGE));
|
||||||
|
|
||||||
|
uv_udp_init(get_task_manager(), &uvRaw);
|
||||||
|
uv_udp_open(&uvRaw, sock);
|
||||||
|
|
||||||
|
uv_udp_recv_start(&uvRaw, alloc_buffer, on_read);
|
||||||
|
|
||||||
|
return ERR_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue