我想在vpp中对dns报文进行拦截和回复,请问在什么位置加入节点
时间: 2024-04-23 07:25:43 浏览: 163
在VPP中对DNS报文进行拦截和回复,需要在数据包处理流程中加入相应的节点。具体来说,可以通过在数据平面的输入节点上添加一个DNS解析节点来实现对DNS报文的拦截和解析。在解析完成后,可以在输出节点上添加一个DNS回复节点,将回复报文发送回客户端。
下面是一个简单的示例,展示了如何在VPP中实现对DNS报文的拦截和回复:
```c
#include <vnet/vnet.h>
#include <vnet/plugin/plugin.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vpp/app/version.h>
#include <vnet/ip/ip.h>
#include <vnet/ip/format.h>
#include <vnet/udp/udp.h>
#include <vnet/dns/dns.h>
// DNS解析节点
static uword dns_parse_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) {
u32 n_left_from, *from, *to_next;
dns_parse_next_t next_index;
vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, dns_parse_node.index);
from = vlib_frame_vector_args(frame);
n_left_from = frame->n_vectors;
while (n_left_from > 0) {
u32 n_left_to_next;
vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
while (n_left_from > 0 && n_left_to_next > 0) {
u32 bi0;
vlib_buffer_t *b0;
u32 next0 = DNS_PARSE_NEXT_DROP;
bi0 = from[0];
b0 = vlib_get_buffer(vm, bi0);
// 解析DNS报文
if (dns_parse(b0)) {
next0 = DNS_PARSE_NEXT_REPLY;
}
to_next[0] = bi0;
to_next += 1;
n_left_to_next -= 1;
from += 1;
n_left_from -= 1;
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0, error_node->node_index, b0->error);
}
vlib_put_next_frame(vm, node, next_index, n_left_to_next);
}
return frame->n_vectors;
}
// DNS回复节点
static uword dns_reply_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame) {
u32 n_left_from, *from, *to_next;
dns_reply_next_t next_index;
vlib_node_runtime_t *error_node = vlib_node_get_runtime(vm, dns_reply_node.index);
from = vlib_frame_vector_args(frame);
n_left_from = frame->n_vectors;
while (n_left_from > 0) {
u32 n_left_to_next;
vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
while (n_left_from > 0 && n_left_to_next > 0) {
u32 bi0;
vlib_buffer_t *b0;
u32 next0 = DNS_REPLY_NEXT_DROP;
bi0 = from[0];
b0 = vlib_get_buffer(vm, bi0);
// 构造DNS回复报文
dns_reply(b0);
to_next[0] = bi0;
to_next += 1;
n_left_to_next -= 1;
from += 1;
n_left_from -= 1;
vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0, error_node->node_index, b0->error);
}
vlib_put_next_frame(vm, node, next_index, n_left_to_next);
}
return frame->n_vectors;
}
// 注册节点
VLIB_REGISTER_NODE(dns_parse_node) = {
.function = dns_parse_node_fn,
.name = "dns-parse",
.vector_size = sizeof(u32),
.format_trace = format_dns_parse_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = DNS_PARSE_N_ERROR,
.error_strings = dns_parse_error_strings,
.n_next_nodes = DNS_PARSE_N_NEXT,
.next_nodes = {
[DNS_PARSE_NEXT_DROP] = "error-drop",
[DNS_PARSE_NEXT_REPLY] = "dns-reply",
},
};
VLIB_REGISTER_NODE(dns_reply_node) = {
.function = dns_reply_node_fn,
.name = "dns-reply",
.vector_size = sizeof(u32),
.format_trace = format_dns_reply_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_errors = DNS_REPLY_N_ERROR,
.error_strings = dns_reply_error_strings,
.n_next_nodes = DNS_REPLY_N_NEXT,
.next_nodes = {
[DNS_REPLY_NEXT_DROP] = "error-drop",
},
};
```
在上述示例中,`dns_parse_node_fn`函数是DNS解析节点的处理函数,`dns_reply_node_fn`函数是DNS回复节点的处理函数。这两个函数分别通过调用`dns_parse`和`dns_reply`函数来实现对DNS报文的解析和回复。其中,`dns_parse`函数用于解析DNS报文,如果解析成功,则将数据包发送到DNS回复节点,否则将数据包丢弃。`dns_reply`函数用于构造DNS回复报文,并将其发送回客户端。
要将这些节点添加到数据平面中,可以使用VPP的API接口或者CLI命令。在API接口中,可以使用`vnet_dns_enable_disable`函数来启用或禁用DNS解析和回复功能。在CLI命令中,可以使用`set dns server`命令来配置DNS服务器地址,使用`set dns domain`命令来配置DNS域名解析规则。
总之,在VPP中实现对DNS报文的拦截和回复,需要通过添加DNS解析节点和DNS回复节点来实现。可以使用VPP的API接口或CLI命令来配置和控制这些节点的行为。
阅读全文