From 3f26ff45dd958c881943a55b7908066e5e42d863 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20Mo=C5=84?= <desowin@gmail.com>
Date: Mon, 17 Nov 2014 18:46:50 +0100
Subject: [PATCH] Do not silence ERR_RTE for tcp write

This makes lwip_send return error if no route is available for example due
to all interfaces being down (for example: after connection was established
someone disconnected network cable).
---
 src/api/api_msg.c  |  4 +++-
 src/core/tcp_out.c | 20 ++++++++++++++------
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/api/api_msg.c b/src/api/api_msg.c
index 2a90e93..94f0929 100644
--- a/src/api/api_msg.c
+++ b/src/api/api_msg.c
@@ -1325,7 +1325,9 @@ err_mem:
         write_finished = 1;
         conn->write_offset = 0;
       }
-      tcp_output(conn->pcb.tcp);
+      /* Store tcp_output return value here so when write_finished is 1,
+         we'll return error to application thread. */
+      err = tcp_output(conn->pcb.tcp);
     } else if ((err == ERR_MEM) && !dontblock) {
       /* If ERR_MEM, we wait for sent_tcp or poll_tcp to be called
          we do NOT return to the application thread, since ERR_MEM is
diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c
index c33a261..93d2c46 100644
--- a/src/core/tcp_out.c
+++ b/src/core/tcp_out.c
@@ -81,7 +81,7 @@
 #endif
 
 /* Forward declarations.*/
-static void tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
+static err_t tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb);
 
 /** Allocate a pbuf and create a tcphdr at p->payload, used for output
  * functions other than the default tcp_output -> tcp_output_segment
@@ -940,6 +940,8 @@ tcp_output(struct tcp_pcb *pcb)
 {
   struct tcp_seg *seg, *useg;
   u32_t wnd, snd_nxt;
+  err_t err;
+
 #if TCP_CWND_DEBUG
   s16_t i = 0;
 #endif /* TCP_CWND_DEBUG */
@@ -1034,7 +1036,10 @@ tcp_output(struct tcp_pcb *pcb)
 #if TCP_OVERSIZE_DBGCHECK
     seg->oversize_left = 0;
 #endif /* TCP_OVERSIZE_DBGCHECK */
-    tcp_output_segment(seg, pcb);
+    err = tcp_output_segment(seg, pcb);
+    if (err != ERR_OK) {
+      return err;
+    }
     snd_nxt = ntohl(seg->tcphdr->seqno) + TCP_TCPLEN(seg);
     if (TCP_SEQ_LT(pcb->snd_nxt, snd_nxt)) {
       pcb->snd_nxt = snd_nxt;
@@ -1088,8 +1093,11 @@ tcp_output(struct tcp_pcb *pcb)
  *
  * @param seg the tcp_seg to send
  * @param pcb the tcp_pcb for the TCP connection used to send the segment
+ *
+ * @return ERR_RTE if no route is found
+ *         see ip_output_if() for more return values
  */
-static void
+static err_t
 tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
 {
   u16_t len;
@@ -1157,7 +1165,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
     ipX_addr_t *local_ip;
     ipX_route_get_local_ipX(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip);
     if ((netif == NULL) || (local_ip == NULL)) {
-      return;
+      return ERR_RTE;
     }
     ipX_addr_copy(PCB_ISIPV6(pcb), pcb->local_ip, *local_ip);
   }
@@ -1220,10 +1228,10 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
   TCP_STATS_INC(tcp.xmit);
 
 #if LWIP_NETIF_HWADDRHINT
-  ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip,
+  return ipX_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip,
     pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint);
 #else /* LWIP_NETIF_HWADDRHINT*/
-  ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
+  return ipX_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
     pcb->tos, IP_PROTO_TCP);
 #endif /* LWIP_NETIF_HWADDRHINT*/
 }
-- 
2.1.1

