Sync to Zebra.org 20030301
diff --git a/zebra/zserv.c b/zebra/zserv.c
index d447d06..e27db44 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -49,6 +49,8 @@
 int rtm_table_default = 0;
 
 void zebra_event (enum event event, int sock, struct zserv *client);
+
+extern struct thread_master *master;
 
 /* For logging of zebra meesages. */
 char *zebra_command_str [] =
@@ -74,6 +76,103 @@
   "ZEBRA_IPV6_IMPORT_LOOKUP"
 };
 
+struct zebra_message_queue
+{
+  struct nsm_message_queue *next;
+  struct nsm_message_queue *prev;
+
+  u_char *buf;
+  u_int16_t length;
+  u_int16_t written;
+};
+
+struct thread *t_write;
+struct fifo message_queue;
+
+int
+zebra_server_dequeue (struct thread *t)
+{
+  int sock;
+  int nbytes;
+  struct zebra_message_queue *queue;
+
+  sock = THREAD_FD (t);
+  t_write = NULL;
+
+  queue = (struct zebra_message_queue *) FIFO_HEAD (&message_queue);
+  if (queue)
+    {
+      nbytes = write (sock, queue->buf + queue->written,
+		      queue->length - queue->written);
+
+      if (nbytes <= 0)
+        {
+          if (errno != EAGAIN)
+	    return -1;
+        }
+      else if (nbytes != (queue->length - queue->written))
+	{
+	  queue->written += nbytes;
+	}
+      else
+        {
+          FIFO_DEL (queue);
+          XFREE (MTYPE_TMP, queue->buf);
+          XFREE (MTYPE_TMP, queue);
+        }
+    }
+
+  if (FIFO_TOP (&message_queue))
+    THREAD_WRITE_ON (master, t_write, zebra_server_dequeue, NULL, sock);
+
+  return 0;
+}
+
+/* Enqueu message.  */
+void
+zebra_server_enqueue (int sock, u_char *buf, unsigned long length,
+		      unsigned long written)
+{
+  struct zebra_message_queue *queue;
+
+  queue = XCALLOC (MTYPE_TMP, sizeof (struct zebra_message_queue));
+  queue->buf = XMALLOC (MTYPE_TMP, length);
+  memcpy (queue->buf, buf, length);
+  queue->length = length;
+  queue->written = written;
+
+  FIFO_ADD (&message_queue, queue);
+
+  THREAD_WRITE_ON (master, t_write, zebra_server_dequeue, NULL, sock);
+}
+
+int
+zebra_server_send_message (int sock, u_char *buf, unsigned long length)
+{
+  int nbytes;
+
+  if (FIFO_TOP (&message_queue))
+    {
+      zebra_server_enqueue (sock, buf, length, 0);
+      return 0;
+    }
+
+  /* Send message.  */
+  nbytes = write (sock, buf, length);
+
+  if (nbytes <= 0)
+    {
+      if (errno == EAGAIN)
+        zebra_server_enqueue (sock, buf, length, 0);
+      else
+	return -1;
+    }
+  else if (nbytes != length)
+    zebra_server_enqueue (sock, buf, length, nbytes);
+
+  return 0;
+}
+
 /* Interface is added. Send ZEBRA_INTERFACE_ADD to client. */
 int
 zsend_interface_add (struct zserv *client, struct interface *ifp)
@@ -112,7 +211,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 /* Interface deletion from zebra daemon. */
@@ -144,7 +245,9 @@
   /* Write packet length. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 /* Interface address is added. Send ZEBRA_INTERFACE_ADDRESS_ADD to the
@@ -190,7 +293,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 /* Interface address is deleted. Send ZEBRA_INTERFACE_ADDRESS_DELETE
@@ -234,7 +339,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -267,7 +374,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -300,7 +409,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -357,7 +468,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -411,7 +524,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -450,7 +565,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -489,7 +606,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 #ifdef HAVE_IPV6
@@ -529,7 +648,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -585,7 +706,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -624,7 +747,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -677,7 +802,9 @@
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
 
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -738,7 +865,9 @@
 
   stream_putw_at (s, 0, stream_get_endp (s));
   
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 #endif /* HAVE_IPV6 */
 
@@ -795,7 +924,9 @@
 
   stream_putw_at (s, 0, stream_get_endp (s));
   
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 int
@@ -851,7 +982,9 @@
 
   stream_putw_at (s, 0, stream_get_endp (s));
   
-  return writen (client->sock, s->data, stream_get_endp (s));
+  zebra_server_send_message (client->sock, s->data, stream_get_endp (s));
+
+  return 0;
 }
 
 /* Register zebra server interface information.  Send current all
@@ -1434,6 +1567,7 @@
 int
 zebra_accept (struct thread *thread)
 {
+  int val;
   int accept_sock;
   int client_sock;
   struct sockaddr_in client;
@@ -1450,6 +1584,11 @@
       return -1;
     }
 
+  /* Make client socket non-blocking.  */
+
+  val = fcntl (client_sock, F_GETFL, 0);
+  fcntl (client_sock, F_SETFL, (val | O_NONBLOCK));
+
   /* Create new zebra client. */
   zebra_client_create (client_sock);
 
@@ -1807,4 +1946,7 @@
   install_element (ENABLE_NODE, &show_ipv6_forwarding_cmd);
   install_element (CONFIG_NODE, &no_ipv6_forwarding_cmd);
 #endif /* HAVE_IPV6 */
+
+  FIFO_INIT(&message_queue);
+  t_write = NULL;
 }