static int do_collect_req(int nl, struct sock_diag_req *req, int size, int (*receive_callback)(struct nlmsghdr *h, void *), void *arg) { int tmp; tmp = do_rtnl_req(nl, req, size, receive_callback, NULL, arg); if (tmp == 0) set_collect_bit(req->r.n.sdiag_family, req->r.n.sdiag_protocol); return tmp; }
/** Dump connections */ int dump_nf_cts(bool expectations, struct cr_img* out) { struct cr_img img = { 0 }; struct { struct nlmsghdr nlh; struct nfgenmsg g; } req; int sk = 0, ret; pr_info("Dumping netns links (table: %s)\n", expectations ? "expect" : "default"); ret = sk = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); if (sk < 0) { pr_perror("Can't open rtnl sock for net dump"); *out = { 0 }; goto out; } memset(&req, 0, sizeof(req)); req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_type = ((expectations ? NFNL_SUBSYS_CTNETLINK_EXP : NFNL_SUBSYS_CTNETLINK) << 8); if (!expectations) req.nlh.nlmsg_type |= IPCTNL_MSG_CT_GET; else req.nlh.nlmsg_type |= IPCTNL_MSG_EXP_GET; req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST; req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_seq = CR_NLMSG_SEQ; req.g.nfgen_family = AF_UNSPEC; ret = do_rtnl_req(sk, &req, sizeof(req), dump_one_nf, NULL, &img); *out = img; out: if (sk != 0) { close(sk); } return ret; }
static inline void probe_diag(int nl, struct sock_diag_req *req, int expected_err) { do_rtnl_req(nl, req, req->hdr.nlmsg_len, probe_recv_one, probe_err, &expected_err); }
/* Restore from buffer */ int restore_nf_cts(bool expectation, char* data, int data_len) { struct nlmsghdr *nlh = NULL; int exit_code = -1, sk; int i = 0; int counter = 0; int res; sk = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); if (sk < 0) { pr_perror("Can't open rtnl sock for net dump"); exit_code = sk; goto out_img; } while (i < data_len) { if (i + sizeof(struct nlmsghdr) > data_len) { break; } nlh = (struct nlmsghdr *)&data[i]; if (i + nlh->nlmsg_len > data_len) { break; } i += nlh->nlmsg_len; if (!expectation) if (ct_restore_callback(nlh)) { pr_info("Unable to adjust CT for restore\n"); exit_code = -EINVAL; goto out; } nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE; res = do_rtnl_req(sk, nlh, nlh->nlmsg_len, NULL, NULL, NULL); if (res) { pr_perror("Unable to insert CT"); exit_code = res; goto out; } counter++; assert(i <= data_len); } if (i == data_len) { exit_code = 0; } else { exit_code = data_len - i; pr_info("%d data is remaining\n", exit_code); } pr_info("%d successfully restored\n", counter); out: close(sk); out_img: return exit_code; }