|
@@ -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;
|
|
|
}
|
|
|
|
|
|
/********************************************************************
|