]> err.no Git - linux-2.6/blobdiff - net/sctp/sm_statefuns.c
Auto-update from upstream
[linux-2.6] / net / sctp / sm_statefuns.c
index 86073df418f5f00e4bf84d44b169ad5b01fe7715..475bfb4972d9ff9a3a4a610877f847031e48c161 100644 (file)
@@ -2414,6 +2414,17 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
        skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
        chunk->subh.shutdown_hdr = sdh;
 
+       /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
+        * When a peer sends a SHUTDOWN, SCTP delivers this notification to
+        * inform the application that it should cease sending data.
+        */
+       ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
+       if (!ev) {
+               disposition = SCTP_DISPOSITION_NOMEM;
+               goto out;       
+       }
+       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+
        /* Upon the reception of the SHUTDOWN, the peer endpoint shall
         *  - enter the SHUTDOWN-RECEIVED state,
         *  - stop accepting new data from its SCTP user
@@ -2439,17 +2450,6 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
        sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
                        SCTP_U32(chunk->subh.shutdown_hdr->cum_tsn_ack));
 
-       /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
-        * When a peer sends a SHUTDOWN, SCTP delivers this notification to
-        * inform the application that it should cease sending data.
-        */
-       ev = sctp_ulpevent_make_shutdown_event(asoc, 0, GFP_ATOMIC);
-       if (!ev) {
-               disposition = SCTP_DISPOSITION_NOMEM;
-               goto out;       
-       }
-       sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
-
 out:
        return disposition;
 }
@@ -5160,6 +5160,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
        sctp_verb_t deliver;
        int tmp;
        __u32 tsn;
+       int account_value;
+       struct sock *sk = asoc->base.sk;
 
        data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data;
        skb_pull(chunk->skb, sizeof(sctp_datahdr_t));
@@ -5169,6 +5171,26 @@ static int sctp_eat_data(const struct sctp_association *asoc,
 
        /* ASSERT:  Now skb->data is really the user data.  */
 
+       /*
+        * if we are established, and we have used up our receive
+        * buffer memory, drop the frame
+        */
+       if (asoc->state == SCTP_STATE_ESTABLISHED) {
+               /*
+                * If the receive buffer policy is 1, then each
+                * association can allocate up to sk_rcvbuf bytes
+                * otherwise, all the associations in aggregate
+                * may allocate up to sk_rcvbuf bytes
+                */
+               if (asoc->ep->rcvbuf_policy)
+                       account_value = atomic_read(&asoc->rmem_alloc);
+               else
+                       account_value = atomic_read(&sk->sk_rmem_alloc);
+
+               if (account_value > sk->sk_rcvbuf)
+                       return SCTP_IERROR_IGNORE_TSN;
+       }
+
        /* Process ECN based congestion.
         *
         * Since the chunk structure is reused for all chunks within