+ struct stat file_stat;
+ char *dir = 0, *tmp;
+ u32 idx = 0;
+
+ /* allow adding socket id 0 */
+ if ((sock_id == 0 && is_add == 0) || sock_id == ~0)
+ {
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (is_add == 0)
+ {
+ return memif_delete_socket_file (sock_id);
+ }
+
+ if (sock_filename == 0 || sock_filename[0] == 0)
+ {
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
+ if (sock_filename[0] != '/')
+ {
+ clib_error_t *error;
+
+ /* copy runtime dir path */
+ vec_add (dir, vlib_unix_get_runtime_dir (),
+ strlen (vlib_unix_get_runtime_dir ()));
+ vec_add1 (dir, '/');
+
+ /* if sock_filename contains dirs, add them to path */
+ tmp = strrchr ((char *) sock_filename, '/');
+ if (tmp)
+ {
+ idx = tmp - (char *) sock_filename;
+ vec_add (dir, sock_filename, idx);
+ }
+
+ vec_add1 (dir, '\0');
+ /* create socket dir */
+ error = vlib_unix_recursive_mkdir (dir);
+ if (error)
+ {
+ clib_error_free (error);
+ return VNET_API_ERROR_SYSCALL_ERROR_1;
+ }
+
+ sock_filename = format (0, "%s/%s%c", vlib_unix_get_runtime_dir (),
+ sock_filename, 0);
+ }
+ else
+ {
+ sock_filename = vec_dup (sock_filename);
+
+ /* check if directory exists */
+ tmp = strrchr ((char *) sock_filename, '/');
+ if (tmp)
+ {
+ idx = tmp - (char *) sock_filename;
+ vec_add (dir, sock_filename, idx);
+ vec_add1 (dir, '\0');
+ }
+
+ if (((dir == 0) || (stat (dir, &file_stat) == -1)
+ || (!S_ISDIR (file_stat.st_mode))) && (idx != 0))
+ {
+ vec_free (dir);
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+ }
+ vec_free (dir);
+
+ return memif_add_socket_file (sock_id, sock_filename);
+}
+
+int
+memif_delete_if (vlib_main_t * vm, memif_if_t * mif)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ memif_main_t *mm = &memif_main;
+ memif_socket_file_t *msf =
+ vec_elt_at_index (mm->socket_files, mif->socket_file_index);
+ clib_error_t *err;
+
+ mif->flags |= MEMIF_IF_FLAG_DELETING;
+ vec_free (mif->local_disc_string);
+ vec_free (mif->remote_disc_string);
+
+ /* bring down the interface */
+ vnet_hw_interface_set_flags (vnm, mif->hw_if_index, 0);
+ vnet_sw_interface_set_flags (vnm, mif->sw_if_index, 0);
+
+ err = clib_error_return (0, "interface deleted");
+ memif_disconnect (mif, err);
+ clib_error_free (err);
+
+ if (mif->hw_if_index != ~0)
+ {
+ /* remove the interface */
+ if (mif->mode == MEMIF_INTERFACE_MODE_IP)
+ vnet_delete_hw_interface (vnm, mif->hw_if_index);
+ else
+ ethernet_delete_interface (vnm, mif->hw_if_index);
+ mif->hw_if_index = ~0;
+ }
+
+ /* free interface data structures */
+ clib_spinlock_free (&mif->lockp);
+ mhash_unset (&msf->dev_instance_by_id, &mif->id, 0);
+
+ /* remove socket file */
+ if (--(msf->ref_cnt) == 0)
+ {
+ if (msf->is_listener)
+ {
+ int i;
+ /* *INDENT-OFF* */
+ vec_foreach_index (i, msf->pending_clients)
+ memif_socket_close (msf->pending_clients + i);
+ /* *INDENT-ON* */
+ memif_socket_close (&msf->sock);
+ vec_free (msf->pending_clients);
+ }
+ mhash_free (&msf->dev_instance_by_id);
+ hash_free (msf->dev_instance_by_fd);
+ if (msf->sock)
+ {
+ err = clib_socket_close (msf->sock);
+ if (err)
+ {
+ memif_log_err (mif, "%U", format_clib_error, err);
+ clib_error_free (err);
+ }
+ clib_mem_free (msf->sock);
+ }
+ }
+
+ memset (mif, 0, sizeof (*mif));
+ pool_put (mm->interfaces, mif);
+
+ if (pool_elts (mm->interfaces) == 0)
+ vlib_process_signal_event (vm, memif_process_node.index,
+ MEMIF_PROCESS_EVENT_STOP, 0);
+