diff --git a/libnozzle/internals.c b/libnozzle/internals.c
index a1e4100..48815e4 100644
--- a/libnozzle/internals.c
+++ b/libnozzle/internals.c
@@ -135,32 +135,6 @@ out_clean0:
 	return err;
 }
 
-int run_updown(const nozzle_t nozzle, const char *action, char **error_string)
-{
-	char command[PATH_MAX];
-	struct stat sb;
-	int err = 0;
-
-	if (!nozzle->hasupdown)
-		return 0;
-
-	memset(command, 0, PATH_MAX);
-
-	snprintf(command, PATH_MAX, "%s%s/%s", nozzle->updownpath, action, nozzle->name);
-
-	err = stat(command, &sb);
-	if ((err < 0) && (errno == ENOENT))
-		return 0;
-
-	err = execute_bin_sh_command(command, error_string);
-	if ((!err) && (*error_string)) {
-		free(*error_string);
-		*error_string = NULL;
-	}
-
-	return err;
-}
-
 char *generate_v4_broadcast(const char *ipaddr, const char *prefix)
 {
 	int prefix_len;
diff --git a/libnozzle/internals.h b/libnozzle/internals.h
index 6a940ee..f6c25a9 100644
--- a/libnozzle/internals.h
+++ b/libnozzle/internals.h
@@ -61,7 +61,6 @@ struct nozzle_iface {
 #define ifname ifr.ifr_name
 
 int execute_bin_sh_command(const char *command, char **error_string);
-int run_updown(const nozzle_t nozzle, const char *action, char **error_string);
 
 int find_ip(nozzle_t nozzle,
 	    const char *ipaddr, const char *prefix,
diff --git a/libnozzle/libnozzle.c b/libnozzle/libnozzle.c
index e8c920b..e9e8b08 100644
--- a/libnozzle/libnozzle.c
+++ b/libnozzle/libnozzle.c
@@ -99,7 +99,7 @@ static int _set_down(nozzle_t nozzle, char **error_down, char **error_postdown)
 		goto out_clean;
 	}
 
-	run_updown(nozzle, "down.d", error_down);
+	nozzle_run_updown(nozzle, NOZZLE_DOWN, error_down);
 
 	ifr.ifr_flags &= ~IFF_UP;
 
@@ -109,7 +109,7 @@ static int _set_down(nozzle_t nozzle, char **error_down, char **error_postdown)
 		goto out_clean;
 	}
 
-	run_updown(nozzle, "post-down.d", error_postdown);
+	nozzle_run_updown(nozzle, NOZZLE_POSTDOWN, error_postdown);
 
 	nozzle->up = 0;
 
@@ -650,7 +650,7 @@ int nozzle_set_up(nozzle_t nozzle, char **error_preup, char **error_up)
 		goto out_clean;
 	}
 
-	run_updown(nozzle, "pre-up.d", error_preup);
+	nozzle_run_updown(nozzle, NOZZLE_PREUP, error_preup);
 
 	ifr.ifr_flags |= IFF_UP | IFF_RUNNING;
 	err = ioctl(lib_cfg.ioctlfd, SIOCSIFFLAGS, &ifr);
@@ -659,7 +659,7 @@ int nozzle_set_up(nozzle_t nozzle, char **error_preup, char **error_up)
 		goto out_clean;
 	}
 
-	run_updown(nozzle, "up.d", error_up);
+	nozzle_run_updown(nozzle, NOZZLE_UP, error_up);
 
 	nozzle->up = 1;
 
@@ -894,6 +894,76 @@ out_clean:
 	return err;
 }
 
+int nozzle_run_updown(const nozzle_t nozzle, uint8_t action, char **error_string)
+{
+	int err = 0, savederrno = 0;
+	char command[PATH_MAX];
+	const char *action_str = NULL;
+	struct stat sb;
+
+	if (action > NOZZLE_POSTDOWN) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (!error_string) {
+		errno = EINVAL;
+		return -1;
+	}
+#if 0
+	savederrno = pthread_mutex_lock(&config_mutex);
+	if (savederrno) {
+		errno = savederrno;
+		return -1;
+	}
+#endif
+	if (!is_valid_nozzle(nozzle)) {
+		savederrno = EINVAL;
+		err = -1;
+		goto out_clean;
+	}
+
+	if (!nozzle->hasupdown) {
+		savederrno = EINVAL;
+		err = -1;
+		goto out_clean;
+	}
+
+	switch(action) {
+		case NOZZLE_PREUP:
+			action_str = "pre-up.d";
+			break;
+		case NOZZLE_UP:
+			action_str = "up.d";
+			break;
+		case NOZZLE_DOWN:
+			action_str = "down.d";
+			break;
+		case NOZZLE_POSTDOWN:
+			action_str = "post-down.d";
+			break;
+	}
+
+	memset(command, 0, PATH_MAX);
+
+	snprintf(command, PATH_MAX, "%s%s/%s", nozzle->updownpath, action_str, nozzle->name);
+
+	err = stat(command, &sb);
+	if ((err < 0) && (errno == ENOENT))
+		return 0;
+
+	err = execute_bin_sh_command(command, error_string);
+	if ((!err) && (*error_string)) {
+		free(*error_string);
+		*error_string = NULL;
+	}
+
+out_clean:
+//	pthread_mutex_unlock(&config_mutex);
+	errno =  savederrno;
+	return err;
+}
+
 /*
  * functions below should be completed
  */
diff --git a/libnozzle/libnozzle.h b/libnozzle/libnozzle.h
index 76d0476..d663b2a 100644
--- a/libnozzle/libnozzle.h
+++ b/libnozzle/libnozzle.h
@@ -77,6 +77,31 @@ nozzle_t nozzle_open(char *devname, size_t devname_size, const char *updownpath)
 
 int nozzle_close(nozzle_t nozzle, char **error_down, char **error_postdown);
 
+
+#define NOZZLE_PREUP    0
+#define NOZZLE_UP       1
+#define NOZZLE_DOWN     2
+#define NOZZLE_POSTDOWN 3
+
+/**
+ * nozzle_run_updown
+ * @brief execute updown commands associated with a nozzle device
+ *
+ * nozzle - pointer to the nozzle struct
+ *
+ * action - pre-up.d / up.d / down.d / post-down.d (see defines above)
+ *
+ * error_string - pointers to string to record errors from executing action.
+ *                The string is malloc'ed, the caller needs to free the buffer.
+ *
+ * @return
+ * 0 on success
+ * -1 on error and errno is set.
+ * error_string will contain strings recording the shell execution error.
+ */
+
+int nozzle_run_updown(const nozzle_t nozzle, uint8_t action, char **error_string);
+
 /**
  * nozzle_set_up
  * @brief equivalent of ifconfig up, executes pre-up.d up.d if configured
