[MINOR] add a generic unbind_listener() primitive

Most protocols will be able to share a single unbind_listener()
primitive. Provided it in protocols.c.
diff --git a/include/proto/protocols.h b/include/proto/protocols.h
index 7b9e1dd..353e4c4 100644
--- a/include/proto/protocols.h
+++ b/include/proto/protocols.h
@@ -51,6 +51,13 @@
  */
 int disable_all_listeners(struct protocol *proto);
 
+/* This function closes the listening socket for the specified listener,
+ * provided that it's already in a listening state. The listener enters the
+ * LI_ASSIGNED state. It always returns ERR_NONE. This function is intended
+ * to be used as a generic function for standard protocols.
+ */
+int unbind_listener(struct listener *listener);
+
 /* Registers the protocol <proto> */
 void protocol_register(struct protocol *proto);
 
diff --git a/src/protocols.c b/src/protocols.c
index 2412d0e..3e118b8 100644
--- a/src/protocols.c
+++ b/src/protocols.c
@@ -20,6 +20,8 @@
 
 #include <types/protocols.h>
 
+#include <proto/fd.h>
+
 /* List head of all registered protocols */
 static struct list protocols = LIST_HEAD_INIT(protocols);
 
@@ -81,6 +83,23 @@
 	return ERR_NONE;
 }
 
+/* This function closes the listening socket for the specified listener,
+ * provided that it's already in a listening state. The listener enters the
+ * LI_ASSIGNED state. It always returns ERR_NONE. This function is intended
+ * to be used as a generic function for standard protocols.
+ */
+int unbind_listener(struct listener *listener)
+{
+	if (listener->state == LI_READY)
+		EV_FD_CLR(listener->fd, DIR_RD);
+
+	if (listener->state >= LI_LISTEN) {
+		fd_delete(listener->fd);
+		listener->state = LI_ASSIGNED;
+	}
+	return ERR_NONE;
+}
+
 /* Registers the protocol <proto> */
 void protocol_register(struct protocol *proto)
 {