pipapo实操笔记


如何创建pipapo_set

关注nf_tables_newset函数中ops的获取:

ops = nft_select_set_ops(&ctx, nla, &desc, policy);
if (IS_ERR(ops))
return PTR_ERR(ops);

跟进到nft_select_set_ops函数:

if (nla[NFTA_SET_FLAGS] != NULL)
flags = ntohl(nla_get_be32(nla[NFTA_SET_FLAGS]));

bops = NULL;
best.size = ~0;
best.lookup = ~0;
best.space = ~0;

for (i = 0; i < ARRAY_SIZE(nft_set_types); i++) {
type = nft_set_types[i];
ops = &type->ops;

if (!nft_set_ops_candidate(type, flags))
continue;
if (!ops->estimate(desc, flags, &est))
continue;

其中nft_set_ops_candidate主要比对feature:

static bool nft_set_ops_candidate(const struct nft_set_type *type, u32 flags)
{
return (flags & type->features) == (flags & NFT_SET_FEATURES);
}

注意pipapo的features如下:

1747646615177

因此最终选择NFT_SET_INTERVAL|NFT_SET_OBJECT|NFT_SET_CONCAT

但是要回到nf_tabels_newset源码中看这些flags的问题:

首先要满足下面三个条件:

1747646705178

此外由于NFT_SET_OBJECT的存在,所以要增加一个NFTA_SET_OBJ_TYPE,这里选择的type是NFT_OBJECT_CT_EXPECT:

1747646737566

除此之外,还要满足pipapo_estimate函数的检查,也就是第二个检查:

1747646850252

这里主要是要给pipapo_set添加field,至少两个,这也好理解,一个就用不着你这破玩意了。。。

所以还要给set添加field,

1747647598233

img

看起来要走NFTA_SET_DESC_CONCAT:

1747647723870

1747647782524

构造格式如下:

{
"NFTA_SET_TABLE":"my_table",
"NFTA_SET_NAME":"my_set@@",
"NFTA_SET_ID":0,
"NFTA_SET_KEY_LEN":16,
"NFTA_SET_FLAGS":196,
"NFTA_SET_OBJ_TYPE":9,
"NFTA_SET_DATA_LEN":16,
"NFTA_SET_DESC":{
"NFTA_SET_DESC_CONCAT":{
"NFTA_LIST_ELEM":{
"NFTA_SET_FIELD_LEN":2
},
"NFTA_LIST_ELEM@1":{
"NFTA_SET_FIELD_LEN":2
}
}
}

}

代码如下:

void create_pipapo_set(int sock){
struct msghdr msg;
struct sockaddr_nl dest_snl;
struct iovec iov[0x100];
struct nlmsghdr *nlh_batch_begin;
struct nlmsghdr *nlh_batch_end;
struct nlattr *attr;
struct nfgenmsg *nfm;

/* Destination preparation */
memset(&dest_snl, 0, sizeof(dest_snl));
dest_snl.nl_family = AF_NETLINK;
memset(&msg, 0, sizeof(msg));

/* Netlink batch_begin message preparation */
nlh_batch_begin = get_batch_begin_nlmsg();


/*
{
"NFTA_SET_TABLE":"my_table",
"NFTA_SET_NAME":"my_set@@",
"NFTA_SET_ID":0,
"NFTA_SET_KEY_LEN":16,
"NFTA_SET_FLAGS":196,
"NFTA_SET_OBJ_TYPE":9,
"NFTA_SET_DATA_LEN":16,
"NFTA_SET_DESC":{
"NFTA_SET_DESC_CONCAT":{
"NFTA_LIST_ELEM":{
"NFTA_SET_FIELD_LEN":2
},
"NFTA_LIST_ELEM@1":{
"NFTA_SET_FIELD_LEN":2
}
}
}

}


*/

int pay1_size = 100; //消息体的大小;
int nlh1_size = NLMSG_SPACE(pay1_size); //整个nlmsghdr的大小

/* Netlink table message preparation */
struct nlmsghdr *nlh1 = (struct nlmsghdr *)malloc(nlh1_size); //这里分配的是整个nlmsghdr的空间

memset(nlh1, 0, nlh1_size);
nlh1->nlmsg_len = nlh1_size;
nlh1->nlmsg_type = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWSET; //注意修改
nlh1->nlmsg_pid = getpid();
nlh1->nlmsg_flags = NLM_F_REQUEST| NLM_F_CREATE;
nlh1->nlmsg_seq = 0;


uint8_t msgcon1[] = {1,0,0,0,12,0,1,0,109,121,95,116,97,98,108,101,12,0,2,0,109,121,95,115,101,116,64,64,8,0,10,0,0,0,0,0,8,0,5,0,0,0,0,16,8,0,3,0,0,0,0,196,8,0,15,0,0,0,0,9,8,0,7,0,0,0,0,16,32,0,9,0,28,0,2,0,12,0,1,0,8,0,1,0,0,0,0,2,12,0,1,0,8,0,1,0,0,0,0,2};
memcpy((void *)nlh1+0x10, msgcon1, pay1_size);

nlh_batch_end = get_batch_end_nlmsg();

/* IOV preparation */
memset(iov, 0, sizeof(iov));
int tot_iov = 0;
iov[tot_iov].iov_base = (void *)nlh_batch_begin;
iov[tot_iov++].iov_len = nlh_batch_begin->nlmsg_len;
iov[tot_iov].iov_base = nlh1;
iov[tot_iov++].iov_len = nlh1->nlmsg_len;
iov[tot_iov].iov_base = (void *)nlh_batch_end;
iov[tot_iov++].iov_len = nlh_batch_end->nlmsg_len;

/* Message header preparation */
msg.msg_name = (void *)&dest_snl;
msg.msg_namelen = sizeof(struct sockaddr_nl);
msg.msg_iov = iov;
msg.msg_iovlen = tot_iov;

sendmsg(sock, &msg, 0);

/* Free used structures */
free(nlh_batch_end);
free(nlh1);
free(nlh_batch_begin);
}

添加元素

还算简单:

{
"NFTA_SET_ELEM_LIST_TABLE":"my_table",
"NFTA_SET_ELEM_LIST_SET":"my_set@@",
"NFTA_SET_ELEM_LIST_ELEMENTS":{
"NONAME":{
"NFTA_SET_ELEM_KEY":{
"NFTA_DATA_VALUE":"1234567812345678"
}

}
}

}

何时insert

1747653621853


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录