]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/sctp/ulpevent.c
DM9000: Add initial ethtool support
[linux-2.6-omap-h63xx.git] / net / sctp / ulpevent.c
index 661ea2dd78baa3f0cd282cc2bf3551a8390480d8..e27b11f18b7f2a32935e9de3a24dd8a4030e7b91 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
@@ -8,13 +8,14 @@
  *
  * These functions manipulate an sctp event.   The struct ulpevent is used
  * to carry notifications and data to the ULP (sockets).
- * The SCTP reference implementation is free software;
+ *
+ * This SCTP implementation is free software;
  * you can redistribute it and/or modify it under the terms of
  * the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation is distributed in the hope that it
  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
  *                 ************************
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -141,11 +142,6 @@ struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(
         * an ABORT, so we need to include it in the sac_info.
         */
        if (chunk) {
-               /* sctp_inqu_pop() has allready pulled off the chunk
-                * header.  We need to put it back temporarily
-                */
-               skb_push(chunk->skb, sizeof(sctp_chunkhdr_t));
-
                /* Copy the chunk data to a new skb and reserve enough
                 * head room to use as notification.
                 */
@@ -155,9 +151,6 @@ struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(
                if (!skb)
                        goto fail;
 
-               /* put back the chunk header now that we have a copy */
-               skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
-
                /* Embed the event fields inside the cloned skb.  */
                event = sctp_skb2event(skb);
                sctp_ulpevent_init(event, MSG_NOTIFICATION, skb->truesize);
@@ -168,7 +161,8 @@ struct sctp_ulpevent  *sctp_ulpevent_make_assoc_change(
 
                /* Trim the buffer to the right length.  */
                skb_trim(skb, sizeof(struct sctp_assoc_change) +
-                        ntohs(chunk->chunk_hdr->length));
+                        ntohs(chunk->chunk_hdr->length) -
+                        sizeof(sctp_chunkhdr_t));
        } else {
                event = sctp_ulpevent_new(sizeof(struct sctp_assoc_change),
                                  MSG_NOTIFICATION, gfp);
@@ -692,6 +686,24 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc,
        struct sctp_ulpevent *event = NULL;
        struct sk_buff *skb;
        size_t padding, len;
+       int rx_count;
+
+       /*
+        * check to see if we need to make space for this
+        * new skb, expand the rcvbuffer if needed, or drop
+        * the frame
+        */
+       if (asoc->ep->rcvbuf_policy)
+               rx_count = atomic_read(&asoc->rmem_alloc);
+       else
+               rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc);
+
+       if (rx_count >= asoc->base.sk->sk_rcvbuf) {
+
+               if ((asoc->base.sk->sk_userlocks & SOCK_RCVBUF_LOCK) ||
+                   (!sk_rmem_schedule(asoc->base.sk, chunk->skb->truesize)))
+                       goto fail;
+       }
 
        /* Clone the original skb, sharing the data.  */
        skb = skb_clone(chunk->skb, gfp);
@@ -802,6 +814,43 @@ fail:
        return NULL;
 }
 
+struct sctp_ulpevent *sctp_ulpevent_make_authkey(
+       const struct sctp_association *asoc, __u16 key_id,
+       __u32 indication, gfp_t gfp)
+{
+       struct sctp_ulpevent *event;
+       struct sctp_authkey_event *ak;
+       struct sk_buff *skb;
+
+       event = sctp_ulpevent_new(sizeof(struct sctp_authkey_event),
+                                 MSG_NOTIFICATION, gfp);
+       if (!event)
+               goto fail;
+
+       skb = sctp_event2skb(event);
+       ak = (struct sctp_authkey_event *)
+               skb_put(skb, sizeof(struct sctp_authkey_event));
+
+       ak->auth_type = SCTP_AUTHENTICATION_INDICATION;
+       ak->auth_flags = 0;
+       ak->auth_length = sizeof(struct sctp_authkey_event);
+
+       ak->auth_keynumber = key_id;
+       ak->auth_altkeynumber = 0;
+       ak->auth_indication = indication;
+
+       /*
+        * The association id field, holds the identifier for the association.
+        */
+       sctp_ulpevent_set_owner(event, asoc);
+       ak->auth_assoc_id = sctp_assoc2id(asoc);
+
+       return event;
+fail:
+       return NULL;
+}
+
+
 /* Return the notification type, assuming this is a notification
  * event.
  */