diff --git a/src/kern/npf_conn.c b/src/kern/npf_conn.c index af2cbc34..f387a0c8 100644 --- a/src/kern/npf_conn.c +++ b/src/kern/npf_conn.c @@ -500,7 +500,7 @@ void npf_conn_destroy(npf_t *npf, npf_conn_t *con) { const npf_connkey_t *key = npf_conn_getforwkey(con); - const unsigned alen = NPF_CONNKEY_ALEN(key); + uint16_t alen = NPF_CONNKEY_ALEN(key); const unsigned idx __unused = NPF_CONNCACHE(alen); KASSERT(con->c_refcnt == 0); @@ -508,6 +508,21 @@ npf_conn_destroy(npf_t *npf, npf_conn_t *con) if (con->c_nat) { /* Release any NAT structures. */ npf_nat_destroy(con->c_nat); + + /* NAT events: execute destroy ipv4 translation callback */ + if (alen == sizeof(in_addr_t) && + npf->nat_events_opts.ipv4_destroy_translation != NULL) { + uint16_t proto; + uint16_t ids[2]; + npf_addr_t ips[2]; + + npf_connkey_getkey(key, &proto, ips, ids, &alen); + npf->nat_events_opts.ipv4_destroy_translation( + proto, ips[NPF_SRC].word32[0], ips[NPF_DST].word32[0], + ids[NPF_SRC], ids[NPF_DST], + npf_nat_gettrans_addr(con->c_nat)->word32[0], + (uint16_t)npf_nat_gettrans_port(con->c_nat)); + } } if (con->c_rproc) { /* Release the rule procedure. */ @@ -543,6 +558,7 @@ npf_conn_setnat(const npf_cache_t *npc, npf_conn_t *con, npf_conn_t *ret __diagused; npf_addr_t *taddr; in_port_t tport; + uint16_t alen; KASSERT(con->c_refcnt > 0); @@ -572,7 +588,8 @@ npf_conn_setnat(const npf_cache_t *npc, npf_conn_t *con, /* Remove the "backwards" key. */ fw = npf_conn_getforwkey(con); - bk = npf_conn_getbackkey(con, NPF_CONNKEY_ALEN(fw)); + alen = NPF_CONNKEY_ALEN(fw); + bk = npf_conn_getbackkey(con, alen); ret = npf_conndb_remove(npf->conn_db, bk); KASSERT(ret == con); @@ -598,6 +615,22 @@ npf_conn_setnat(const npf_cache_t *npc, npf_conn_t *con, /* Associate the NAT entry and release the lock. */ con->c_nat = nt; mutex_exit(&con->c_lock); + + /* NAT events: execute create ipv4 translation callback */ + if (alen == sizeof(in_addr_t) && + npf->nat_events_opts.ipv4_create_translation != NULL) { + uint16_t proto; + uint16_t ids[2]; + npf_addr_t ips[2]; + + npf_connkey_getkey(fw, &proto, ips, ids, &alen); + npf->nat_events_opts.ipv4_create_translation( + proto, ips[NPF_SRC].word32[0], ips[NPF_DST].word32[0], + ids[NPF_SRC], ids[NPF_DST], + npf_nat_gettrans_addr(con->c_nat)->word32[0], + (uint16_t)npf_nat_gettrans_port(con->c_nat)); + } + return 0; } diff --git a/src/kern/npf_conn.h b/src/kern/npf_conn.h index c2222e84..b089cbe2 100644 --- a/src/kern/npf_conn.h +++ b/src/kern/npf_conn.h @@ -113,7 +113,6 @@ npf_connkey_t * npf_conn_getforwkey(npf_conn_t *); npf_connkey_t * npf_conn_getbackkey(npf_conn_t *, unsigned); void npf_conn_adjkey(npf_connkey_t *, const npf_addr_t *, const uint16_t, const int); - unsigned npf_connkey_import(const nvlist_t *, npf_connkey_t *); nvlist_t * npf_connkey_export(const npf_connkey_t *); void npf_connkey_print(const npf_connkey_t *); diff --git a/src/kern/npf_impl.h b/src/kern/npf_impl.h index a22abf3e..8c8e8b62 100644 --- a/src/kern/npf_impl.h +++ b/src/kern/npf_impl.h @@ -237,6 +237,9 @@ struct npf { /* Statistics. */ percpu_t * stats_percpu; + + /* NAT events callbacks */ + npf_nat_events_ops_t nat_events_opts; }; /* @@ -481,6 +484,8 @@ int npf_do_nat(npf_cache_t *, npf_conn_t *, const int); void npf_nat_destroy(npf_nat_t *); void npf_nat_getorig(npf_nat_t *, npf_addr_t **, in_port_t *); void npf_nat_gettrans(npf_nat_t *, npf_addr_t **, in_port_t *); +const npf_addr_t * npf_nat_gettrans_addr(const npf_nat_t *); +in_port_t npf_nat_gettrans_port(const npf_nat_t *); void npf_nat_setalg(npf_nat_t *, npf_alg_t *, uintptr_t); void npf_nat_export(nvlist_t *, npf_nat_t *); diff --git a/src/kern/npf_nat.c b/src/kern/npf_nat.c index 1fddfae3..ddec4eba 100644 --- a/src/kern/npf_nat.c +++ b/src/kern/npf_nat.c @@ -709,6 +709,18 @@ npf_nat_gettrans(npf_nat_t *nt, npf_addr_t **addr, in_port_t *port) *port = nt->nt_tport; } +const npf_addr_t * +npf_nat_gettrans_addr(const npf_nat_t *nt) +{ + return &nt->nt_taddr; +} + +in_port_t +npf_nat_gettrans_port(const npf_nat_t *nt) +{ + return nt->nt_tport; +} + /* * npf_nat_getorig: return original IP address and port from translation entry. */ @@ -839,3 +851,17 @@ npf_nat_dump(const npf_nat_t *nt) } #endif + +__dso_public void +npf_nat_events_set_create_ipv4_translation_cb(npf_t *npf, + npf_nat_event_ipv4_create_translation_t cb) +{ + npf->nat_events_opts.ipv4_create_translation = cb; +} + +__dso_public void +npf_nat_events_set_destroy_ipv4_translation_cb(npf_t *npf, + npf_nat_event_ipv4_destroy_translation_t cb) +{ + npf->nat_events_opts.ipv4_destroy_translation = cb; +} \ No newline at end of file diff --git a/src/kern/npfkern.h b/src/kern/npfkern.h index 7d69b589..4a3a54b3 100644 --- a/src/kern/npfkern.h +++ b/src/kern/npfkern.h @@ -61,6 +61,20 @@ typedef struct { bool (*ensure_writable)(struct mbuf **, size_t); } npf_mbufops_t; +/* NAT event callbacks */ +typedef void (*npf_nat_event_ipv4_create_translation_t) (uint16_t proto, + uint32_t src, uint32_t dst, uint16_t src_id, uint16_t dst_id, + uint32_t tsrc, uint16_t tsrc_id); + +typedef void (*npf_nat_event_ipv4_destroy_translation_t) (uint16_t proto, + uint32_t src, uint32_t dst, uint16_t src_id, uint16_t dst_id, + uint32_t tsrc, uint16_t tsrc_id); + +typedef struct { + npf_nat_event_ipv4_create_translation_t ipv4_create_translation; + npf_nat_event_ipv4_destroy_translation_t ipv4_destroy_translation; +} npf_nat_events_ops_t; + int npf_sysinit(unsigned); void npf_sysfini(void); @@ -86,4 +100,10 @@ void npf_stats_clear(npf_t *); int npf_alg_icmp_init(npf_t *); int npf_alg_icmp_fini(npf_t *); +/* NAT events callbacks */ +void npf_nat_events_set_create_ipv4_translation_cb(npf_t *, + npf_nat_event_ipv4_create_translation_t); +void npf_nat_events_set_destroy_ipv4_translation_cb(npf_t *, + npf_nat_event_ipv4_destroy_translation_t); + #endif