fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / net / sctp / endpointola.c
index 5f9a99c..1297569 100644 (file)
 #include <net/sctp/sm.h>
 
 /* Forward declarations for internal helpers. */
-static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep);
-
-/* Create a sctp_endpoint with all that boring stuff initialized.
- * Returns NULL if there isn't enough memory.
- */
-struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, int gfp)
-{
-       struct sctp_endpoint *ep;
-
-       /* Build a local endpoint. */
-       ep = t_new(struct sctp_endpoint, gfp);
-       if (!ep)
-               goto fail;
-       if (!sctp_endpoint_init(ep, sk, gfp))
-               goto fail_init;
-       ep->base.malloced = 1;
-       SCTP_DBG_OBJCNT_INC(ep);
-       return ep;
-
-fail_init:
-       kfree(ep);
-fail:
-       return NULL;
-}
+static void sctp_endpoint_bh_rcv(struct work_struct *work);
 
 /*
  * Initialize the base fields of the endpoint structure.
  */
-struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
-                                        struct sock *sk, int gfp)
+static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
+                                               struct sock *sk,
+                                               gfp_t gfp)
 {
-       struct sctp_opt *sp = sctp_sk(sk);
        memset(ep, 0, sizeof(struct sctp_endpoint));
 
+       ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp);
+       if (!ep->digest)
+               return NULL;
+
        /* Initialize the base structure. */
        /* What type of endpoint are we?  */
        ep->base.type = SCTP_EP_TYPE_SOCKET;
@@ -108,12 +89,11 @@ struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
        sctp_inq_init(&ep->base.inqueue);
 
        /* Set its top-half handler */
-       sctp_inq_set_th_handler(&ep->base.inqueue,
-                               (void (*)(void *))sctp_endpoint_bh_rcv, ep);
+       sctp_inq_set_th_handler(&ep->base.inqueue, sctp_endpoint_bh_rcv);
 
        /* Initialize the bind addr area */
        sctp_bind_addr_init(&ep->base.bind_addr, 0);
-       ep->base.addr_lock = RW_LOCK_UNLOCKED;
+       rwlock_init(&ep->base.addr_lock);
 
        /* Remember who we are attached to.  */
        ep->base.sk = sk;
@@ -122,50 +102,58 @@ struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
        /* Create the lists of associations.  */
        INIT_LIST_HEAD(&ep->asocs);
 
-       /* Set up the base timeout information.  */
-       ep->timeouts[SCTP_EVENT_TIMEOUT_NONE] = 0;
-       ep->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE] =
-               SCTP_DEFAULT_TIMEOUT_T1_COOKIE;
-       ep->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT] =
-               SCTP_DEFAULT_TIMEOUT_T1_INIT;
-       ep->timeouts[SCTP_EVENT_TIMEOUT_T2_SHUTDOWN] =
-               msecs_to_jiffies(sp->rtoinfo.srto_initial);
-       ep->timeouts[SCTP_EVENT_TIMEOUT_T3_RTX] = 0;
-       ep->timeouts[SCTP_EVENT_TIMEOUT_T4_RTO] = 0;
-
-       /* sctpimpguide-05 Section 2.12.2
-        * If the 'T5-shutdown-guard' timer is used, it SHOULD be set to the
-        * recommended value of 5 times 'RTO.Max'.
-        */
-        ep->timeouts[SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD]
-               = 5 * msecs_to_jiffies(sp->rtoinfo.srto_max);
-
-       ep->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] =
-               SCTP_DEFAULT_TIMEOUT_HEARTBEAT;
-       ep->timeouts[SCTP_EVENT_TIMEOUT_SACK] =
-               SCTP_DEFAULT_TIMEOUT_SACK;
-       ep->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
-               sp->autoclose * HZ;
-
        /* Use SCTP specific send buffer space queues.  */
+       ep->sndbuf_policy = sctp_sndbuf_policy;
        sk->sk_write_space = sctp_write_space;
-       sk->sk_use_write_queue = 1;
+       sock_set_flag(sk, SOCK_USE_WRITE_QUEUE);
+
+       /* Get the receive buffer policy for this endpoint */
+       ep->rcvbuf_policy = sctp_rcvbuf_policy;
 
        /* Initialize the secret key used with cookie. */
        get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE);
        ep->last_key = ep->current_key = 0;
        ep->key_changed_at = jiffies;
 
-       ep->debug_name = "unnamedEndpoint";
        return ep;
 }
 
+/* Create a sctp_endpoint with all that boring stuff initialized.
+ * Returns NULL if there isn't enough memory.
+ */
+struct sctp_endpoint *sctp_endpoint_new(struct sock *sk, gfp_t gfp)
+{
+       struct sctp_endpoint *ep;
+
+       /* Build a local endpoint. */
+       ep = t_new(struct sctp_endpoint, gfp);
+       if (!ep)
+               goto fail;
+       if (!sctp_endpoint_init(ep, sk, gfp))
+               goto fail_init;
+       ep->base.malloced = 1;
+       SCTP_DBG_OBJCNT_INC(ep);
+       return ep;
+
+fail_init:
+       kfree(ep);
+fail:
+       return NULL;
+}
+
 /* Add an association to an endpoint.  */
 void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
                            struct sctp_association *asoc)
 {
        struct sock *sk = ep->base.sk;
 
+       /* If this is a temporary association, don't bother
+        * since we'll be removing it shortly and don't
+        * want anyone to find it anyway.
+        */
+       if (asoc->temp)
+               return;
+
        /* Now just add it to our list of asocs */
        list_add_tail(&asoc->asocs, &ep->asocs);
 
@@ -180,22 +168,25 @@ void sctp_endpoint_add_asoc(struct sctp_endpoint *ep,
 void sctp_endpoint_free(struct sctp_endpoint *ep)
 {
        ep->base.dead = 1;
+
+       ep->base.sk->sk_state = SCTP_SS_CLOSED;
+
+       /* Unlink this endpoint, so we can't find it again! */
+       sctp_unhash_endpoint(ep);
+
        sctp_endpoint_put(ep);
 }
 
 /* Final destructor for endpoint.  */
-void sctp_endpoint_destroy(struct sctp_endpoint *ep)
+static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
 {
        SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return);
 
-       ep->base.sk->sk_state = SCTP_SS_CLOSED;
-
-       /* Unlink this endpoint, so we can't find it again! */
-       sctp_unhash_endpoint(ep);
-
        /* Free up the HMAC transform. */
-       if (sctp_sk(ep->base.sk)->hmac)
-               sctp_crypto_free_tfm(sctp_sk(ep->base.sk)->hmac);
+       crypto_free_hash(sctp_sk(ep->base.sk)->hmac);
+
+       /* Free the digest buffer */
+       kfree(ep->digest);
 
        /* Cleanup. */
        sctp_inq_free(&ep->base.inqueue);
@@ -238,7 +229,7 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
        struct sctp_endpoint *retval;
 
        sctp_read_lock(&ep->base.addr_lock);
-       if (ep->base.bind_addr.port == laddr->v4.sin_port) {
+       if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) {
                if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
                                         sctp_sk(ep->base.sk))) {
                        retval = ep;
@@ -257,7 +248,7 @@ out:
  * We do a linear search of the associations for this endpoint.
  * We return the matching transport address too.
  */
-struct sctp_association *__sctp_endpoint_lookup_assoc(
+static struct sctp_association *__sctp_endpoint_lookup_assoc(
        const struct sctp_endpoint *ep,
        const union sctp_addr *paddr,
        struct sctp_transport **transport)
@@ -266,7 +257,7 @@ struct sctp_association *__sctp_endpoint_lookup_assoc(
        struct sctp_association *asoc;
        struct list_head *pos;
 
-       rport = paddr->v4.sin_port;
+       rport = ntohs(paddr->v4.sin_port);
 
        list_for_each(pos, &ep->asocs) {
                asoc = list_entry(pos, struct sctp_association, asocs);
@@ -326,8 +317,11 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
 /* Do delayed input processing.  This is scheduled by sctp_rcv().
  * This may be called on BH or task time.
  */
-static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
+static void sctp_endpoint_bh_rcv(struct work_struct *work)
 {
+       struct sctp_endpoint *ep =
+               container_of(work, struct sctp_endpoint,
+                            base.inqueue.immediate);
        struct sctp_association *asoc;
        struct sock *sk;
        struct sctp_transport *transport;
@@ -345,7 +339,7 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
        sk = ep->base.sk;
 
        while (NULL != (chunk = sctp_inq_pop(inqueue))) {
-               subtype.chunk = chunk->chunk_hdr->type;
+               subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type);
 
                /* We might have grown an association since last we
                 * looked, so try again.
@@ -369,7 +363,7 @@ static void sctp_endpoint_bh_rcv(struct sctp_endpoint *ep)
                if (asoc && sctp_chunk_is_data(chunk))
                        asoc->peer.last_data_from = chunk->transport;
                else
-                       SCTP_INC_STATS(SctpInCtrlChunks);
+                       SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS);
 
                if (chunk->transport)
                        chunk->transport->last_time_heard = jiffies;