+static clib_error_t *
+punt_socket_register_cmd (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ bool is_ipv4 = true;
+ u32 protocol = ~0;
+ u32 port = ~0;
+ u8 *socket_name = 0;
+ clib_error_t *error = NULL;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "ipv4"))
+ ;
+ else if (unformat (input, "ipv6"))
+ is_ipv4 = false;
+ else if (unformat (input, "udp"))
+ protocol = IP_PROTOCOL_UDP;
+ else if (unformat (input, "tcp"))
+ protocol = IP_PROTOCOL_TCP;
+ else if (unformat (input, "%d", &port))
+ ;
+ else if (unformat (input, "socket %s", &socket_name))
+ ;
+ else
+ {
+ error = clib_error_return (0, "parse error: '%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+ }
+
+ error =
+ vnet_punt_socket_add (vm, 1, is_ipv4, protocol, port,
+ (char *) socket_name);
+ if (error)
+ {
+ goto done;
+ }
+done:
+ return error;
+}
+
+/*?
+ *
+ * @cliexpar
+ * @cliexcmd{punt socket register}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (punt_socket_register_command, static) =
+{
+ .path = "punt socket register",
+ .function = punt_socket_register_cmd,
+ .short_help = "punt socket register [ipv4|ipv6] [udp|tcp]> <all | port-num1 [port-num2 ...]> <socket>",
+ .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
+
+static clib_error_t *
+punt_socket_deregister_cmd (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ bool is_ipv4 = true;
+ u32 protocol = ~0;
+ u32 port = ~0;
+ clib_error_t *error = NULL;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "ipv4"))
+ ;
+ else if (unformat (input, "ipv6"))
+ is_ipv4 = false;
+ else if (unformat (input, "udp"))
+ protocol = IP_PROTOCOL_UDP;
+ else if (unformat (input, "tcp"))
+ protocol = IP_PROTOCOL_TCP;
+ else if (unformat (input, "%d", &port))
+ ;
+ else
+ {
+ error = clib_error_return (0, "parse error: '%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+ }
+
+ error = vnet_punt_socket_del (vm, is_ipv4, protocol, port);
+ if (error)
+ {
+ goto done;
+ }
+done:
+ return error;
+}
+
+/*?
+ *
+ * @cliexpar
+ * @cliexcmd{punt socket register}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (punt_socket_deregister_command, static) =
+{
+ .path = "punt socket deregister",
+ .function = punt_socket_deregister_cmd,
+ .short_help = "punt socket deregister [ipv4|ipv6] [udp|tcp]> <all | port-num1 [port-num2 ...]>",
+ .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
+
+punt_socket_detail_t *
+punt_socket_entries (u8 ipv)
+{
+ punt_main_t *pm = &punt_main;
+ punt_client_t *pc;
+ punt_socket_detail_t *ps = 0;
+ bool is_valid;
+
+ punt_client_t *v = !ipv ? pm->clients_by_dst_port4 :
+ pm->clients_by_dst_port6;
+
+ vec_foreach (pc, v)
+ {
+ if (pc && pc->port != 0)
+ {
+ is_valid = false;
+ if (pc->protocol == IP_PROTOCOL_UDP)
+ {
+ is_valid = udp_is_valid_dst_port (pc->port, !ipv);
+ }
+ if (is_valid)
+ {
+ punt_socket_detail_t detail = {
+ .ipv = ipv,
+ .l4_protocol = pc->protocol,
+ .l4_port = pc->port
+ };
+ memcpy (detail.pathname, pc->caddr.sun_path,
+ sizeof (pc->caddr.sun_path));
+ vec_add1 (ps, detail);
+ }
+ }
+ }
+ return ps;
+}
+
+u8 *
+format_punt_socket (u8 * s, va_list * args)
+{
+ punt_client_t *clients = va_arg (*args, punt_client_t *);
+ u8 *is_ipv6 = va_arg (*args, u8 *);
+ punt_client_t *pc;
+ bool is_valid;
+
+ vec_foreach (pc, clients)
+ {
+ if (pc && pc->port != 0)
+ {
+ is_valid = false;
+ if (pc->protocol == IP_PROTOCOL_UDP)
+ {
+ is_valid = udp_is_valid_dst_port (pc->port, !(*is_ipv6));
+ }
+ if (is_valid)
+ {
+ s = format (s, " punt %s port %d to socket %s \n",
+ (pc->protocol == IP_PROTOCOL_UDP) ? "UDP" : "TCP",
+ pc->port, pc->caddr.sun_path);
+ }
+ }
+ }
+
+ return (s);
+}
+
+static clib_error_t *
+punt_socket_show_cmd (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cmd)
+{
+ u8 is_ipv6;
+ punt_main_t *pm = &punt_main;
+ clib_error_t *error = NULL;
+
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "ipv4"))
+ is_ipv6 = 0;
+ else if (unformat (input, "ipv6"))
+ is_ipv6 = 1;
+ else
+ {
+ error = clib_error_return (0, "parse error: '%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+ }
+
+ punt_client_t *v =
+ is_ipv6 ? pm->clients_by_dst_port6 : pm->clients_by_dst_port4;
+ vlib_cli_output (vm, "%U", format_punt_socket, v, &is_ipv6);
+
+done:
+ return (error);
+}
+
+/*?
+ *
+ * @cliexpar
+ * @cliexcmd{show punt socket ipv4}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (show_punt_socket_registration_command, static) =
+{
+ .path = "show punt socket registrations",
+ .function = punt_socket_show_cmd,
+ .short_help = "show punt socket registrations [ipv4|ipv6]",
+ .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
+