tunnels: fix netns vs proto registration ordering
[safe/jmp/linux-2.6] / net / sctp / ulpevent.c
index b43f1f1..8b3560f 100644 (file)
@@ -710,6 +710,13 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        if (!skb)
                goto fail;
 
+       /* Now that all memory allocations for this chunk succeeded, we
+        * can mark it as received so the tsn_map is updated correctly.
+        */
+       if (sctp_tsnmap_mark(&asoc->peer.tsn_map,
+                            ntohl(chunk->subh.data_hdr->tsn)))
+               goto fail_mark;
+
        /* First calculate the padding, so we don't inadvertently
         * pass up the wrong length to the user.
         *
@@ -750,8 +757,12 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        event->msg_flags |= chunk->chunk_hdr->flags;
        event->iif = sctp_chunk_iif(chunk);
 
-fail:
        return event;
+
+fail_mark:
+       kfree_skb(skb);
+fail:
+       return NULL;
 }
 
 /* Create a partial delivery related event.
@@ -859,7 +870,7 @@ __u16 sctp_ulpevent_get_notification_type(const struct sctp_ulpevent *event)
        union sctp_notification *notification;
        struct sk_buff *skb;
 
-       skb = sctp_event2skb((struct sctp_ulpevent *)event);
+       skb = sctp_event2skb(event);
        notification = (union sctp_notification *) skb->data;
        return notification->sn_header.sn_type;
 }
@@ -965,9 +976,8 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event,
         * In general, the skb passed from IP can have only 1 level of
         * fragments. But we allow multiple levels of fragments.
         */
-       for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+       skb_walk_frags(skb, frag)
                sctp_ulpevent_receive_data(sctp_skb2event(frag), asoc);
-       }
 }
 
 /* Do accounting for bytes just read by user and release the references to
@@ -992,7 +1002,7 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event)
                goto done;
 
        /* Don't forget the fragments. */
-       for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+       skb_walk_frags(skb, frag) {
                /* NOTE:  skb_shinfos are recursive. Although IP returns
                 * skb's with only 1 level of fragments, SCTP reassembly can
                 * increase the levels.
@@ -1015,7 +1025,7 @@ static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event)
                goto done;
 
        /* Don't forget the fragments. */
-       for (frag = skb_shinfo(skb)->frag_list; frag; frag = frag->next) {
+       skb_walk_frags(skb, frag) {
                /* NOTE:  skb_shinfos are recursive. Although IP returns
                 * skb's with only 1 level of fragments, SCTP reassembly can
                 * increase the levels.