static int parse(char c, struct nf_conntrack *ct, struct nf_conntrack *exptuple, struct nf_conntrack *mask, unsigned int *flags) { switch(c) { u_int8_t tmp; u_int16_t id; case '1': tmp = atoi(optarg); nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, tmp); nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMP); *flags |= CT_ICMP_TYPE; break; case '2': tmp = atoi(optarg); nfct_set_attr_u8(ct, ATTR_ICMP_CODE, tmp); nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMP); *flags |= CT_ICMP_CODE; break; case '3': id = htons(atoi(optarg)); nfct_set_attr_u16(ct, ATTR_ICMP_ID, id); nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMP); *flags |= CT_ICMP_ID; break; } return 1; }
int main() { int ret; struct nfct_handle *h; struct nf_conntrack *ct; ct = nfct_new(); if (!ct) { perror("nfct_new"); return 0; } nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(ct, ATTR_IPV4_SRC, inet_addr("1.1.1.1")); nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr("2.2.2.2")); nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20)); nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10)); h = nfct_open(CONNTRACK, 0); if (!h) { perror("nfct_open"); return -1; } ret = nfct_query(h, NFCT_Q_DESTROY, ct); printf("TEST: delete conntrack (%d)(%s)\n", ret, strerror(errno)); if (ret == -1) exit(EXIT_FAILURE); nfct_close(h); }
static PyObject* ForwardingRule_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { ForwardingRule *self; self = (ForwardingRule*) type->tp_alloc(type, 0); if (self != NULL) { self->is_active = 0; self->done_init = 0; self->prev = NULL; self->next = NULL; memset(self->counter, 0, sizeof(uint32_t) * 4); if ((self->dict = PyDict_New()) == NULL) { Py_DECREF(self); return NULL; } if ((self->conntrack = nfct_new()) == NULL) { Py_DECREF(self->dict); Py_DECREF(self); PyErr_NoMemory(); return NULL; } nfct_set_attr_u8(self->conntrack, ATTR_ORIG_L3PROTO, AF_INET); nfct_set_attr_u8(self->conntrack, ATTR_ORIG_L4PROTO, IPPROTO_UDP); } return (PyObject*) self; }
static void l4_tcp_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct) { const struct tcphdr *tcph = (const struct tcphdr *)pkt; nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_TCP); nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, tcph->source); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, tcph->dest); nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, tcph->dest); nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, tcph->source); }
/* So, this packet has hit the connection tracking matching code. Mangle it, and change the expectation to match the new version. */ static unsigned int nf_nat_rpc(struct pkt_buff *pkt, int dir, struct nf_expect *exp, uint8_t proto, uint32_t *port_ptr) { const struct nf_conntrack *expected; struct nf_conntrack *nat_tuple; uint16_t initial_port, port; expected = nfexp_get_attr(exp, ATTR_EXP_EXPECTED); nat_tuple = nfct_new(); if (nat_tuple == NULL) return NF_ACCEPT; initial_port = nfct_get_attr_u16(expected, ATTR_PORT_DST); nfexp_set_attr_u32(exp, ATTR_EXP_NAT_DIR, !dir); /* libnetfilter_conntrack needs this */ nfct_set_attr_u8(nat_tuple, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(nat_tuple, ATTR_IPV4_SRC, 0); nfct_set_attr_u32(nat_tuple, ATTR_IPV4_DST, 0); nfct_set_attr_u8(nat_tuple, ATTR_L4PROTO, proto); nfct_set_attr_u16(nat_tuple, ATTR_PORT_DST, 0); /* When you see the packet, we need to NAT it the same as the * this one. */ nfexp_set_attr(exp, ATTR_EXP_FN, "nat-follow-master"); /* Try to get same port: if not, try to change it. */ for (port = ntohs(initial_port); port != 0; port++) { int ret; nfct_set_attr_u16(nat_tuple, ATTR_PORT_SRC, htons(port)); nfexp_set_attr(exp, ATTR_EXP_NAT_TUPLE, nat_tuple); ret = cthelper_add_expect(exp); if (ret == 0) break; else if (ret != -EBUSY) { port = 0; break; } } nfct_destroy(nat_tuple); if (port == 0) return NF_DROP; *port_ptr = htonl(port); return NF_ACCEPT; }
int main(void) { int ret; struct nfct_handle *h; struct nf_conntrack *expected; struct nf_expect *exp; expected = nfct_new(); if (!expected) { perror("nfct_new"); exit(EXIT_FAILURE); } nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(expected, ATTR_IPV4_SRC, inet_addr("1.1.1.1")); nfct_set_attr_u32(expected, ATTR_IPV4_DST, inet_addr("2.2.2.2")); nfct_set_attr_u8(expected, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0); nfct_set_attr_u16(expected, ATTR_PORT_DST, htons(10241)); exp = nfexp_new(); if (!exp) { perror("nfexp_new"); nfct_destroy(expected); exit(EXIT_FAILURE); } nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected); h = nfct_open(EXPECT, 0); if (!h) { perror("nfct_open"); nfct_destroy(expected); return -1; } ret = nfexp_query(h, NFCT_Q_DESTROY, exp); printf("TEST: delete expectation "); if (ret == -1) printf("(%d)(%s)\n", ret, strerror(errno)); else printf("(OK)\n"); nfct_close(h); nfct_destroy(expected); ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS); }
static int parse_options(char c, struct nf_conntrack *ct, struct nf_conntrack *exptuple, struct nf_conntrack *mask, unsigned int *flags) { switch(c) { u_int16_t port; case '1': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port); nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_ORIG_SKEY; break; case '2': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, port); nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_ORIG_DKEY; break; case '3': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, port); nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_REPL_SKEY; break; case '4': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, port); nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_REPL_DKEY; break; case '5': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(mask, ATTR_ORIG_PORT_SRC, port); nfct_set_attr_u8(mask, ATTR_ORIG_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_MASK_SKEY; break; case '6': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(mask, ATTR_ORIG_PORT_DST, port); nfct_set_attr_u8(mask, ATTR_ORIG_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_MASK_DKEY; break; case '7': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(exptuple, ATTR_ORIG_PORT_SRC, port); nfct_set_attr_u8(exptuple, ATTR_ORIG_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_EXPTUPLE_SKEY; break; case '8': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(exptuple, ATTR_ORIG_PORT_DST, port); nfct_set_attr_u8(exptuple, ATTR_ORIG_L4PROTO, IPPROTO_GRE); *flags |= CT_GRE_EXPTUPLE_DKEY; break; } return 1; }
int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr, int istcp, unsigned int *markp) { struct nf_conntrack *ct; struct nfct_handle *h; gotit = 0; if ((ct = nfct_new())) { nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP); nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port)); #ifdef HAVE_IPV6 if (peer_addr->sa.sa_family == AF_INET6) { nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6); nfct_set_attr(ct, ATTR_IPV6_SRC, peer_addr->in6.sin6_addr.s6_addr); nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in6.sin6_port); nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr.addr6.s6_addr); } else #endif { nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr); nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in.sin_port); nfct_set_attr_u32(ct, ATTR_IPV4_DST, local_addr->addr.addr4.s_addr); } if ((h = nfct_open(CONNTRACK, 0))) { nfct_callback_register(h, NFCT_T_ALL, callback, (void *)markp); if (nfct_query(h, NFCT_Q_GET, ct) == -1) { static int warned = 0; if (!warned) { my_syslog(LOG_ERR, _("Conntrack connection mark retrieval failed: %s"), strerror(errno)); warned = 1; } } nfct_close(h); } nfct_destroy(ct); } return gotit; }
int nl_create_conntrack(struct nfct_handle *h, const struct nf_conntrack *orig, int timeout) { int ret; struct nf_conntrack *ct; ct = nfct_clone(orig); if (ct == NULL) return -1; if (timeout > 0) nfct_set_attr_u32(ct, ATTR_TIMEOUT, timeout); /* we hit error if we try to change the expected bit */ if (nfct_attr_is_set(ct, ATTR_STATUS)) { uint32_t status = nfct_get_attr_u32(ct, ATTR_STATUS); status &= ~IPS_EXPECTED; nfct_set_attr_u32(ct, ATTR_STATUS, status); } nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY); /* disable TCP window tracking for recovered connections if required */ if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) { uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM; if (!CONFIG(sync).tcp_window_tracking) flags |= IP_CT_TCP_FLAG_BE_LIBERAL; else flags |= IP_CT_TCP_FLAG_WINDOW_SCALE; /* FIXME: workaround, we should send TCP flags in updates */ if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >= TCP_CONNTRACK_TIME_WAIT) { flags |= IP_CT_TCP_FLAG_CLOSE_INIT; } nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags); nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags); nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags); nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags); } ret = nfct_query(h, NFCT_Q_CREATE, ct); nfct_destroy(ct); return ret; }
int main() { int ret; struct nfct_handle *h; struct nf_conntrack *ct; ct = nfct_new(); if (!ct) { perror("nfct_new"); return 0; } nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(ct, ATTR_IPV4_SRC, inet_addr("1.1.1.1")); nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr("2.2.2.2")); nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20)); nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10)); nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY); nfct_set_attr_u8(ct, ATTR_TCP_STATE, TCP_CONNTRACK_LISTEN); nfct_set_attr_u32(ct, ATTR_TIMEOUT, 100); nfct_set_attr_u32(ct, ATTR_SNAT_IPV4, inet_addr("8.8.8.8")); h = nfct_open(CONNTRACK, 0); if (!h) { perror("nfct_open"); return -1; } ret = nfct_query(h, NFCT_Q_CREATE, ct); printf("TEST: create conntrack (%d)(%s)\n", ret, strerror(errno)); if (ret == -1) exit(EXIT_FAILURE); nfct_close(h); }
static int test_nfct_cmp_api_single(struct nf_conntrack *ct1, struct nf_conntrack *ct2, int attr) { char data[256]; struct nfct_bitmask *b; int bit; if (attr_is_readonly(attr)) return 0; switch (attr) { case ATTR_SECMARK: /* obsolete */ return 0; /* FIXME: not implemented comparators: */ case ATTR_SNAT_IPV4: case ATTR_DNAT_IPV4: case ATTR_SNAT_PORT: case ATTR_DNAT_PORT: case ATTR_TCP_FLAGS_ORIG: case ATTR_TCP_FLAGS_REPL: case ATTR_TCP_MASK_ORIG: case ATTR_TCP_MASK_REPL: case ATTR_MASTER_IPV4_SRC: case ATTR_MASTER_IPV4_DST: case ATTR_MASTER_IPV6_SRC: case ATTR_MASTER_IPV6_DST: case ATTR_MASTER_PORT_SRC: case ATTR_MASTER_PORT_DST: case ATTR_MASTER_L3PROTO: case ATTR_MASTER_L4PROTO: case ATTR_ORIG_NAT_SEQ_CORRECTION_POS: case ATTR_ORIG_NAT_SEQ_OFFSET_BEFORE: case ATTR_ORIG_NAT_SEQ_OFFSET_AFTER: case ATTR_REPL_NAT_SEQ_CORRECTION_POS: case ATTR_REPL_NAT_SEQ_OFFSET_BEFORE: case ATTR_REPL_NAT_SEQ_OFFSET_AFTER: case ATTR_SCTP_VTAG_ORIG: case ATTR_SCTP_VTAG_REPL: case ATTR_HELPER_NAME: case ATTR_DCCP_ROLE: case ATTR_DCCP_HANDSHAKE_SEQ: case ATTR_TCP_WSCALE_ORIG: case ATTR_TCP_WSCALE_REPL: case ATTR_HELPER_INFO: return 0; /* XXX */ default: break; } if (attr >= ATTR_SCTP_STATE) { nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_SCTP); nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_SCTP); } else if (attr >= ATTR_TCP_FLAGS_ORIG) { nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP); nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP); } else if (attr >= ATTR_ICMP_CODE) { nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_ICMP); nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_ICMP); } else if (attr >= ATTR_ORIG_PORT_SRC) { nfct_set_attr_u8(ct1, ATTR_REPL_L4PROTO, IPPROTO_TCP); nfct_set_attr_u8(ct1, ATTR_L4PROTO, IPPROTO_TCP); } nfct_copy(ct2, ct1, NFCT_CP_OVERRIDE); memset(data, 42, sizeof(data)); assert(nfct_attr_is_set(ct1, attr)); assert(nfct_attr_is_set(ct2, attr)); switch (attr) { case ATTR_CONNLABELS: case ATTR_CONNLABELS_MASK: b = (void *) nfct_get_attr(ct1, attr); assert(b); b = nfct_bitmask_clone(b); assert(b); bit = nfct_bitmask_maxbit(b); if (nfct_bitmask_test_bit(b, bit)) { nfct_bitmask_unset_bit(b, bit); assert(!nfct_bitmask_test_bit(b, bit)); } else { nfct_bitmask_set_bit(b, bit); assert(nfct_bitmask_test_bit(b, bit)); } assert(nfct_cmp(ct1, ct2, NFCT_CMP_ALL) == 1); nfct_set_attr(ct2, attr, b); break; case ATTR_HELPER_INFO: nfct_set_attr_l(ct2, attr, "test", 4); break; default: nfct_set_attr(ct2, attr, data); break; } if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL) != 0) { fprintf(stderr, "nfct_cmp assert failure for attr %d\n", attr); fprintf(stderr, "%p, %p, %x, %x\n", nfct_get_attr(ct1, attr), nfct_get_attr(ct2, attr), nfct_get_attr_u32(ct1, attr), nfct_get_attr_u32(ct2, attr)); return -1; } if (nfct_cmp(ct1, ct2, NFCT_CMP_ALL|NFCT_CMP_STRICT) != 0) { fprintf(stderr, "nfct_cmp strict assert failure for attr %d\n", attr); return -1; } return 0; }
int main(void) { struct mnl_socket *nl; struct nlmsghdr *nlh; struct nfgenmsg *nfh; char buf[MNL_SOCKET_BUFFER_SIZE]; unsigned int seq, portid; struct nf_conntrack *ct; int ret; nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { perror("mnl_socket_open"); exit(EXIT_FAILURE); } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { perror("mnl_socket_bind"); exit(EXIT_FAILURE); } portid = mnl_socket_get_portid(nl); nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_DELETE; nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlh->nlmsg_seq = seq = time(NULL); nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = AF_INET; nfh->version = NFNETLINK_V0; nfh->res_id = 0; ct = nfct_new(); if (ct == NULL) { perror("nfct_new"); return 0; } nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(ct, ATTR_IPV4_SRC, inet_addr("1.1.1.1")); nfct_set_attr_u32(ct, ATTR_IPV4_DST, inet_addr("2.2.2.2")); nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20)); nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10)); nfct_nlmsg_build(nlh, ct); ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); if (ret <= MNL_CB_STOP) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) { perror("mnl_socket_recvfrom"); exit(EXIT_FAILURE); } mnl_socket_close(nl); return 0; }
int nl_update_conntrack(struct nfct_handle *h, const struct nf_conntrack *orig, int timeout) { int ret; struct nf_conntrack *ct; ct = nfct_clone(orig); if (ct == NULL) return -1; if (timeout > 0) nfct_set_attr_u32(ct, ATTR_TIMEOUT, timeout); /* unset NAT info, otherwise we hit error */ nfct_attr_unset(ct, ATTR_SNAT_IPV4); nfct_attr_unset(ct, ATTR_DNAT_IPV4); nfct_attr_unset(ct, ATTR_SNAT_PORT); nfct_attr_unset(ct, ATTR_DNAT_PORT); if (nfct_attr_is_set(ct, ATTR_STATUS)) { uint32_t status = nfct_get_attr_u32(ct, ATTR_STATUS); status &= ~IPS_NAT_MASK; nfct_set_attr_u32(ct, ATTR_STATUS, status); } /* we have to unset the helper to avoid EBUSY in reset timers */ if (nfct_attr_is_set(ct, ATTR_HELPER_NAME)) nfct_attr_unset(ct, ATTR_HELPER_NAME); /* we hit error if we try to update the master conntrack */ if (ct_is_related(ct)) { nfct_attr_unset(ct, ATTR_MASTER_L3PROTO); nfct_attr_unset(ct, ATTR_MASTER_L4PROTO); nfct_attr_unset(ct, ATTR_MASTER_IPV4_SRC); nfct_attr_unset(ct, ATTR_MASTER_IPV4_DST); nfct_attr_unset(ct, ATTR_MASTER_IPV6_SRC); nfct_attr_unset(ct, ATTR_MASTER_IPV6_DST); nfct_attr_unset(ct, ATTR_MASTER_PORT_SRC); nfct_attr_unset(ct, ATTR_MASTER_PORT_DST); } /* disable TCP window tracking for recovered connections if required */ if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) { uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM; if (!CONFIG(sync).tcp_window_tracking) flags |= IP_CT_TCP_FLAG_BE_LIBERAL; else flags |= IP_CT_TCP_FLAG_WINDOW_SCALE; /* FIXME: workaround, we should send TCP flags in updates */ if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >= TCP_CONNTRACK_TIME_WAIT) { flags |= IP_CT_TCP_FLAG_CLOSE_INIT; } nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_ORIG, flags); nfct_set_attr_u8(ct, ATTR_TCP_MASK_ORIG, flags); nfct_set_attr_u8(ct, ATTR_TCP_FLAGS_REPL, flags); nfct_set_attr_u8(ct, ATTR_TCP_MASK_REPL, flags); } ret = nfct_query(h, NFCT_Q_UPDATE, ct); nfct_destroy(ct); return ret; }
int main(void) { int ret; struct nfct_handle *h; struct nf_conntrack *master, *expected, *mask, *nat; struct nf_expect *exp; /* * Step 1: Setup master conntrack */ master = nfct_new(); if (!master) { perror("nfct_new"); exit(EXIT_FAILURE); } nfct_set_attr_u8(master, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(master, ATTR_IPV4_SRC, inet_addr("1.1.1.1")); nfct_set_attr_u32(master, ATTR_IPV4_DST, inet_addr("2.2.2.2")); nfct_set_attr_u8(master, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(master, ATTR_PORT_SRC, htons(1025)); nfct_set_attr_u16(master, ATTR_PORT_DST, htons(21)); nfct_setobjopt(master, NFCT_SOPT_SETUP_REPLY); nfct_set_attr_u8(master, ATTR_TCP_STATE, TCP_CONNTRACK_ESTABLISHED); nfct_set_attr_u32(master, ATTR_TIMEOUT, 200); nfct_set_attr(master, ATTR_HELPER_NAME, "ftp"); h = nfct_open(CONNTRACK, 0); if (!h) { perror("nfct_open"); nfct_destroy(master); return -1; } ret = nfct_query(h, NFCT_Q_CREATE, master); printf("TEST: add master conntrack "); if (ret == -1) printf("(%d)(%s)\n", ret, strerror(errno)); else printf("(OK)\n"); nfct_close(h); expected = nfct_new(); if (!expected) { perror("nfct_new"); exit(EXIT_FAILURE); } nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(expected, ATTR_IPV4_SRC, inet_addr("1.1.1.1")); nfct_set_attr_u32(expected, ATTR_IPV4_DST, inet_addr("2.2.2.2")); nfct_set_attr_u8(expected, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0); nfct_set_attr_u16(expected, ATTR_PORT_DST, htons(10241)); mask = nfct_new(); if (!mask) { perror("nfct_new"); nfct_destroy(master); nfct_destroy(expected); exit(EXIT_FAILURE); } nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0xffffffff); nfct_set_attr_u32(mask, ATTR_IPV4_DST, 0xffffffff); nfct_set_attr_u8(mask, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0x0000); nfct_set_attr_u16(mask, ATTR_PORT_DST, 0xffff); nat = nfct_new(); if (!nat) { perror("nfct_new"); nfct_destroy(mask); nfct_destroy(master); nfct_destroy(expected); exit(EXIT_FAILURE); } nfct_set_attr_u8(nat, ATTR_L3PROTO, AF_INET); nfct_set_attr_u32(nat, ATTR_IPV4_SRC, inet_addr("3.3.3.3")); nfct_set_attr_u32(nat, ATTR_IPV4_DST, 0); nfct_set_attr_u8(nat, ATTR_L4PROTO, IPPROTO_TCP); nfct_set_attr_u16(nat, ATTR_PORT_SRC, 12345); nfct_set_attr_u16(nat, ATTR_PORT_DST, 0); /* * Step 2: Setup expectation */ exp = nfexp_new(); if (!exp) { perror("nfexp_new"); nfct_destroy(master); nfct_destroy(expected); nfct_destroy(mask); exit(EXIT_FAILURE); } nfexp_set_attr(exp, ATTR_EXP_MASTER, master); nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected); nfexp_set_attr(exp, ATTR_EXP_MASK, mask); nfexp_set_attr(exp, ATTR_EXP_NAT_TUPLE, nat); nfexp_set_attr_u32(exp, ATTR_EXP_NAT_DIR, 0); nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, 200); nfct_destroy(master); nfct_destroy(expected); nfct_destroy(mask); nfct_destroy(nat); h = nfct_open(EXPECT, 0); if (!h) { perror("nfct_open"); return -1; } ret = nfexp_query(h, NFCT_Q_CREATE, exp); printf("TEST: create expectation "); if (ret == -1) printf("(%d)(%s)\n", ret, strerror(errno)); else printf("(OK)\n"); nfct_close(h); ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS); }
int get_nat_ext_addr(struct sockaddr* src, struct sockaddr *dst, uint8_t proto, struct sockaddr_storage* ret_ext) { struct mnl_socket *nl; struct nlmsghdr *nlh; struct nfgenmsg *nfh; char buf[MNL_SOCKET_BUFFER_SIZE]; unsigned int seq, portid; struct nf_conntrack *ct; int ret; struct data_cb_s data; if ((!src)&&(!dst)) { return 0; } if (src->sa_family != dst->sa_family) { return 0; } nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) { // perror("mnl_socket_open"); goto free_nl; } if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { // perror("mnl_socket_bind"); goto free_nl; } portid = mnl_socket_get_portid(nl); memset(buf, 0, sizeof(buf)); nlh = mnl_nlmsg_put_header(buf); nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | IPCTNL_MSG_CT_GET; nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_ACK; nlh->nlmsg_seq = seq = time(NULL); nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); nfh->nfgen_family = src->sa_family; nfh->version = NFNETLINK_V0; nfh->res_id = 0; ct = nfct_new(); if (ct == NULL) { goto free_nl; } nfct_set_attr_u8(ct, ATTR_L3PROTO, src->sa_family); if (src->sa_family == AF_INET) { struct sockaddr_in *src4 = (struct sockaddr_in *)src; struct sockaddr_in *dst4 = (struct sockaddr_in *)dst; nfct_set_attr_u32(ct, ATTR_IPV4_SRC, src4->sin_addr.s_addr); nfct_set_attr_u32(ct, ATTR_IPV4_DST, dst4->sin_addr.s_addr); nfct_set_attr_u16(ct, ATTR_PORT_SRC, src4->sin_port); nfct_set_attr_u16(ct, ATTR_PORT_DST, dst4->sin_port); } else if (src->sa_family == AF_INET6) { struct sockaddr_in6 *src6 = (struct sockaddr_in6 *)src; struct sockaddr_in6 *dst6 = (struct sockaddr_in6 *)dst; nfct_set_attr(ct, ATTR_IPV6_SRC, &src6->sin6_addr); nfct_set_attr(ct, ATTR_IPV6_DST, &dst6->sin6_addr); nfct_set_attr_u16(ct, ATTR_PORT_SRC, src6->sin6_port); nfct_set_attr_u16(ct, ATTR_PORT_DST, dst6->sin6_port); } nfct_set_attr_u8(ct, ATTR_L4PROTO, proto); nfct_nlmsg_build(nlh, ct); ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); if (ret == -1) { goto free_ct; } ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); data.ext = ret_ext; data.found = 0; while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, data_cb, &data); if (ret <= MNL_CB_STOP) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } free_ct: nfct_destroy(ct); free_nl: mnl_socket_close(nl); return data.found; }