+static void
+send_snat_user_details
+(snat_user_t * u, unix_shared_memory_queue_t * q, u32 context)
+{
+ vl_api_snat_user_details_t * rmp;
+ snat_main_t * sm = &snat_main;
+ ip4_fib_t * fib_table;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_DETAILS+sm->msg_id_base);
+
+ fib_table = ip4_fib_get(u->fib_index);
+ rmp->vrf_id = ntohl (fib_table->table_id);
+
+ rmp->is_ip4 = 1;
+ clib_memcpy(rmp->ip_address, &(u->addr), 4);
+ rmp->nsessions = ntohl (u->nsessions);
+ rmp->nstaticsessions = ntohl (u->nstaticsessions);
+ rmp->context = context;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+vl_api_snat_user_dump_t_handler
+(vl_api_snat_user_dump_t * mp)
+{
+ unix_shared_memory_queue_t *q;
+ snat_main_t * sm = &snat_main;
+ snat_main_per_thread_data_t * tsm;
+ snat_user_t * u;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ vec_foreach (tsm, sm->per_thread_data)
+ vec_foreach (u, tsm->users)
+ send_snat_user_details (u, q, mp->context);
+}
+
+static void *vl_api_snat_user_dump_t_print
+(vl_api_snat_user_dump_t *mp, void * handle)
+{
+ u8 *s;
+
+ s = format (0, "SCRIPT: snat_user_dump ");
+
+ FINISH;
+}
+
+static void
+send_snat_user_session_details
+(snat_session_t * s, unix_shared_memory_queue_t * q, u32 context)
+{
+ vl_api_snat_user_session_details_t * rmp;
+ snat_main_t * sm = &snat_main;
+
+ rmp = vl_msg_api_alloc (sizeof(*rmp));
+ memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_SNAT_USER_SESSION_DETAILS+sm->msg_id_base);
+ rmp->is_ip4 = 1;
+ clib_memcpy(rmp->outside_ip_address, (&s->out2in.addr), 4);
+ rmp->outside_port = s->out2in.port;
+ clib_memcpy(rmp->inside_ip_address, (&s->in2out.addr), 4);
+ rmp->inside_port = s->in2out.port;
+ rmp->protocol = ntohs(snat_proto_to_ip_proto(s->in2out.protocol));
+ rmp->is_static = s->flags & SNAT_SESSION_FLAG_STATIC_MAPPING ? 1 : 0;
+ rmp->last_heard = clib_host_to_net_u64((u64)s->last_heard);
+ rmp->total_bytes = clib_host_to_net_u64(s->total_bytes);
+ rmp->total_pkts = ntohl(s->total_pkts);
+ rmp->context = context;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+vl_api_snat_user_session_dump_t_handler
+(vl_api_snat_user_session_dump_t * mp)
+{
+ unix_shared_memory_queue_t *q;
+ snat_main_t * sm = &snat_main;
+ snat_main_per_thread_data_t *tsm;
+ snat_session_t * s;
+ clib_bihash_kv_8_8_t key, value;
+ snat_user_key_t ukey;
+ snat_user_t * u;
+ u32 session_index, head_index, elt_index;
+ dlist_elt_t * head, * elt;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+ if (!mp->is_ip4)
+ return;
+
+ clib_memcpy (&ukey.addr, mp->ip_address, 4);
+ ukey.fib_index = ip4_fib_index_from_table_id (ntohl(mp->vrf_id));
+ key.key = ukey.as_u64;
+ if (!clib_bihash_search_8_8 (&sm->worker_by_in, &key, &value))
+ tsm = vec_elt_at_index (sm->per_thread_data, value.value);
+ else
+ tsm = vec_elt_at_index (sm->per_thread_data, sm->num_workers);
+ if (clib_bihash_search_8_8 (&sm->user_hash, &key, &value))
+ return;
+ u = pool_elt_at_index (tsm->users, value.value);
+ if (!u->nsessions && !u->nstaticsessions)
+ return;
+
+ head_index = u->sessions_per_user_list_head_index;
+ head = pool_elt_at_index (tsm->list_pool, head_index);
+ elt_index = head->next;
+ elt = pool_elt_at_index (tsm->list_pool, elt_index);
+ session_index = elt->value;
+ while (session_index != ~0)
+ {
+ s = pool_elt_at_index (tsm->sessions, session_index);
+
+ send_snat_user_session_details (s, q, mp->context);
+
+ elt_index = elt->next;
+ elt = pool_elt_at_index (tsm->list_pool, elt_index);
+ session_index = elt->value;
+ }
+}
+
+static void *vl_api_snat_user_session_dump_t_print
+(vl_api_snat_user_session_dump_t *mp, void * handle)
+{
+ u8 *s;
+
+ s = format (0, "SCRIPT: snat_user_session_dump ");
+ s = format (s, "ip_address %U vrf_id %d\n",
+ format_ip4_address, mp->ip_address,
+ clib_net_to_host_u32 (mp->vrf_id));
+
+ FINISH;
+}
+
+static void
+vl_api_snat_add_det_map_t_handler
+(vl_api_snat_add_det_map_t * mp)
+{
+ snat_main_t * sm = &snat_main;
+ vl_api_snat_add_det_map_reply_t * rmp;
+ int rv = 0;
+ ip4_address_t in_addr, out_addr;
+
+ clib_memcpy(&in_addr, mp->in_addr, 4);
+ clib_memcpy(&out_addr, mp->out_addr, 4);
+ rv = snat_det_add_map(sm, &in_addr, mp->in_plen, &out_addr,
+ mp->out_plen, mp->is_add);
+
+ REPLY_MACRO (VL_API_SNAT_ADD_DET_MAP_REPLY);
+}
+
+static void *vl_api_snat_add_det_map_t_print
+(vl_api_snat_add_det_map_t *mp, void * handle)
+{
+ u8 * s;
+
+ s = format (0, "SCRIPT: snat_add_det_map ");
+ s = format (s, "inside address %U/%d outside address %U/%d\n",
+ format_ip4_address, mp->in_addr, mp->in_plen,
+ format_ip4_address, mp->out_addr, mp->out_plen);
+
+ FINISH;
+}
+
+static void
+vl_api_snat_det_forward_t_handler
+(vl_api_snat_det_forward_t * mp)
+{
+ snat_main_t * sm = &snat_main;
+ vl_api_snat_det_forward_reply_t * rmp;
+ int rv = 0;
+ u16 lo_port = 0, hi_port = 0;
+ snat_det_map_t * dm;
+ ip4_address_t in_addr, out_addr;
+
+ out_addr.as_u32 = 0;
+ clib_memcpy(&in_addr, mp->in_addr, 4);
+ dm = snat_det_map_by_user(sm, &in_addr);
+ if (!dm)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_ENTRY;
+ goto send_reply;
+ }
+
+ snat_det_forward(dm, &in_addr, &out_addr, &lo_port);
+ hi_port = lo_port + dm->ports_per_host - 1;
+
+send_reply:
+ REPLY_MACRO2(VL_API_SNAT_DET_FORWARD_REPLY,
+ ({
+ rmp->out_port_lo = ntohs(lo_port);
+ rmp->out_port_hi = ntohs(hi_port);
+ rmp->is_ip4 = 1;
+ memset(rmp->out_addr, 0, 16);
+ clib_memcpy(rmp->out_addr, &out_addr, 4);
+ }))
+}
+
+static void *vl_api_snat_det_forward_t_print
+(vl_api_snat_det_forward_t * mp, void * handle)
+{
+ u8 * s;
+
+ s = format (0, "SCRIPT: smat_det_forward_t");
+ s = format (s, "inside ip address %U\n",
+ format_ip4_address, mp->in_addr);
+
+ FINISH;
+}
+
+static void
+vl_api_snat_det_reverse_t_handler
+(vl_api_snat_det_reverse_t * mp)
+{
+ snat_main_t * sm = &snat_main;
+ vl_api_snat_det_reverse_reply_t * rmp;
+ int rv = 0;
+ ip4_address_t out_addr, in_addr;
+ snat_det_map_t * dm;
+
+ in_addr.as_u32 = 0;
+ clib_memcpy(&out_addr, mp->out_addr, 4);
+ dm = snat_det_map_by_out(sm, &out_addr);
+ if (!dm)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_ENTRY;
+ goto send_reply;
+ }
+
+ snat_det_reverse(dm, &out_addr, htons(mp->out_port), &in_addr);
+
+ send_reply:
+ REPLY_MACRO2(VL_API_SNAT_DET_REVERSE_REPLY,
+ ({
+ rmp->is_ip4 = 1;
+ memset(rmp->in_addr, 0, 16);
+ clib_memcpy(rmp->in_addr, &in_addr, 4);
+ }))
+}
+
+static void *vl_api_snat_det_reverse_t_print
+(vl_api_snat_det_reverse_t * mp, void * handle)
+{
+ u8 * s;
+
+ s = format(0, "SCRIPT: smat_det_reverse_t");
+ s = format(s, "outside ip address %U outside port %d",
+ format_ip4_address, mp->out_addr, ntohs(mp->out_port));
+
+ FINISH;
+}
+
+static void
+sent_snat_det_map_details
+(snat_det_map_t * m, unix_shared_memory_queue_t * q, u32 context)
+{
+ vl_api_snat_det_map_details_t *rmp;
+ snat_main_t * sm = &snat_main;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_SNAT_DET_MAP_DETAILS+sm->msg_id_base);
+ rmp->is_ip4 = 1;
+ clib_memcpy (rmp->in_addr, &m->in_addr, 4);
+ rmp->in_plen = m->in_plen;
+ clib_memcpy (rmp->out_addr, &m->out_addr, 4);
+ rmp->out_plen = m->out_plen;
+ rmp->sharing_ratio = htonl (m->sharing_ratio);
+ rmp->ports_per_host = htons (m->ports_per_host);
+ rmp->ses_num = htonl (m->ses_num);
+ rmp->context = context;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+vl_api_snat_det_map_dump_t_handler
+(vl_api_snat_det_map_dump_t * mp)
+{
+ unix_shared_memory_queue_t *q;
+ snat_main_t * sm = &snat_main;
+ snat_det_map_t * m;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ vec_foreach(m, sm->det_maps)
+ sent_snat_det_map_details(m, q, mp->context);
+}
+
+static void * vl_api_snat_det_map_dump_t_print
+(vl_api_snat_det_map_dump_t *mp, void * handle)
+{
+ u8 * s;
+
+ s = format (0, "SCRIPT: snat_det_map_dump ");
+
+ FINISH;
+}
+