sctp: not return ENOMEM err back in sctp_packet_transmit
[cascardo/linux.git] / net / sctp / output.c
index f2597a9..0c605ec 100644 (file)
@@ -442,14 +442,14 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
                         * time. Application may notice this error.
                         */
                        pr_err_once("Trying to GSO but underlying device doesn't support it.");
-                       goto nomem;
+                       goto err;
                }
        } else {
                pkt_size = packet->size;
        }
        head = alloc_skb(pkt_size + MAX_HEADER, gfp);
        if (!head)
-               goto nomem;
+               goto err;
        if (gso) {
                NAPI_GRO_CB(head)->last = head;
                skb_shinfo(head)->gso_type = sk->sk_gso_type;
@@ -470,8 +470,12 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
                }
        }
        dst = dst_clone(tp->dst);
-       if (!dst)
-               goto no_route;
+       if (!dst) {
+               if (asoc)
+                       IP_INC_STATS(sock_net(asoc->base.sk),
+                                    IPSTATS_MIB_OUTNOROUTES);
+               goto nodst;
+       }
        skb_dst_set(head, dst);
 
        /* Build the SCTP header.  */
@@ -622,8 +626,10 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
                if (!gso)
                        break;
 
-               if (skb_gro_receive(&head, nskb))
+               if (skb_gro_receive(&head, nskb)) {
+                       kfree_skb(nskb);
                        goto nomem;
+               }
                nskb = NULL;
                if (WARN_ON_ONCE(skb_shinfo(head)->gso_segs >=
                                 sk->sk_gso_max_segs))
@@ -717,18 +723,13 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
        }
        head->ignore_df = packet->ipfragok;
        tp->af_specific->sctp_xmit(head, tp);
+       goto out;
 
-out:
-       sctp_packet_reset(packet);
-       return err;
-no_route:
-       kfree_skb(head);
-       if (nskb != head)
-               kfree_skb(nskb);
-
-       if (asoc)
-               IP_INC_STATS(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES);
+nomem:
+       if (packet->auth && list_empty(&packet->auth->list))
+               sctp_chunk_free(packet->auth);
 
+nodst:
        /* FIXME: Returning the 'err' will effect all the associations
         * associated with a socket, although only one of the paths of the
         * association is unreachable.
@@ -737,22 +738,18 @@ no_route:
         * required.
         */
         /* err = -EHOSTUNREACH; */
-err:
-       /* Control chunks are unreliable so just drop them.  DATA chunks
-        * will get resent or dropped later.
-        */
+       kfree_skb(head);
 
+err:
        list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
                list_del_init(&chunk->list);
                if (!sctp_chunk_is_data(chunk))
                        sctp_chunk_free(chunk);
        }
-       goto out;
-nomem:
-       if (packet->auth && list_empty(&packet->auth->list))
-               sctp_chunk_free(packet->auth);
-       err = -ENOMEM;
-       goto err;
+
+out:
+       sctp_packet_reset(packet);
+       return err;
 }
 
 /********************************************************************