Merge master.kernel.org:/pub/scm/linux/kernel/git/sridhar/lksctp-2.6
authorDavid S. Miller <davem@sunset.davemloft.net>
Fri, 20 Jan 2006 00:53:02 +0000 (16:53 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 20 Jan 2006 00:53:02 +0000 (16:53 -0800)
include/net/sctp/sctp.h
include/net/sctp/structs.h
net/sctp/input.c
net/sctp/inqueue.c
net/sctp/proc.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/transport.c

index a553f39..e673b2c 100644 (file)
@@ -175,6 +175,8 @@ void sctp_icmp_frag_needed(struct sock *, struct sctp_association *,
 void sctp_icmp_proto_unreachable(struct sock *sk,
                                 struct sctp_association *asoc,
                                 struct sctp_transport *t);
+void sctp_backlog_migrate(struct sctp_association *assoc,
+                         struct sock *oldsk, struct sock *newsk);
 
 /*
  *  Section:  Macros, externs, and inlines
index f5c22d7..8c522ae 100644 (file)
@@ -127,9 +127,9 @@ extern struct sctp_globals {
         * RTO.Alpha                - 1/8  (3 when converted to right shifts.)
         * RTO.Beta                 - 1/4  (2 when converted to right shifts.)
         */
-       __u32 rto_initial;
-       __u32 rto_min;
-       __u32 rto_max;
+       unsigned long rto_initial;
+       unsigned long rto_min;
+       unsigned long rto_max;
 
        /* Note: rto_alpha and rto_beta are really defined as inverse
         * powers of two to facilitate integer operations.
@@ -140,12 +140,18 @@ extern struct sctp_globals {
        /* Max.Burst                - 4 */
        int max_burst;
 
-       /* Valid.Cookie.Life        - 60  seconds  */
-       int valid_cookie_life;
-
        /* Whether Cookie Preservative is enabled(1) or not(0) */
        int cookie_preserve_enable;
 
+       /* Valid.Cookie.Life        - 60  seconds  */
+       unsigned long valid_cookie_life;
+
+       /* Delayed SACK timeout  200ms default*/
+       unsigned long sack_timeout;
+
+       /* HB.interval              - 30 seconds  */
+       unsigned long hb_interval;
+
        /* Association.Max.Retrans  - 10 attempts
         * Path.Max.Retrans         - 5  attempts (per destination address)
         * Max.Init.Retransmits     - 8  attempts
@@ -168,12 +174,6 @@ extern struct sctp_globals {
         */
        int rcvbuf_policy;
 
-       /* Delayed SACK timeout  200ms default*/
-       int sack_timeout;
-
-       /* HB.interval              - 30 seconds  */
-       int hb_interval;
-
        /* The following variables are implementation specific.  */
 
        /* Default initialization values to be applied to new associations. */
@@ -405,8 +405,9 @@ struct sctp_cookie {
 /* The format of our cookie that we send to our peer. */
 struct sctp_signed_cookie {
        __u8 signature[SCTP_SECRET_SIZE];
+       __u32 __pad;            /* force sctp_cookie alignment to 64 bits */
        struct sctp_cookie c;
-};
+} __attribute__((packed));
 
 /* This is another convenience type to allocate memory for address
  * params for the maximum size and pass such structures around
@@ -827,7 +828,7 @@ struct sctp_transport {
        __u32 rtt;              /* This is the most recent RTT.  */
 
        /* RTO         : The current retransmission timeout value.  */
-       __u32 rto;
+       unsigned long rto;
 
        /* RTTVAR      : The current RTT variation.  */
        __u32 rttvar;
@@ -877,22 +878,10 @@ struct sctp_transport {
        /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
         * the destination address every heartbeat interval.
         */
-       __u32 hbinterval;
-
-       /* This is the max_retrans value for the transport and will
-        * be initialized from the assocs value.  This can be changed
-        * using SCTP_SET_PEER_ADDR_PARAMS socket option.
-        */
-       __u16 pathmaxrxt;
-
-       /* PMTU       : The current known path MTU.  */
-       __u32 pathmtu;
+       unsigned long hbinterval;
 
        /* SACK delay timeout */
-       __u32 sackdelay;
-
-       /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
-       __u32 param_flags;
+       unsigned long sackdelay;
 
        /* When was the last time (in jiffies) that we heard from this
         * transport?  We use this to pick new active and retran paths.
@@ -904,6 +893,18 @@ struct sctp_transport {
         */
        unsigned long last_time_ecne_reduced;
 
+       /* This is the max_retrans value for the transport and will
+        * be initialized from the assocs value.  This can be changed
+        * using SCTP_SET_PEER_ADDR_PARAMS socket option.
+        */
+       __u16 pathmaxrxt;
+
+       /* PMTU       : The current known path MTU.  */
+       __u32 pathmtu;
+
+       /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
+       __u32 param_flags;
+
        /* The number of times INIT has been sent on this transport. */
        int init_sent_count;
 
@@ -1249,6 +1250,14 @@ struct sctp_endpoint {
        int last_key;
        int key_changed_at;
 
+       /* digest:  This is a digest of the sctp cookie.  This field is
+        *          only used on the receive path when we try to validate
+        *          that the cookie has not been tampered with.  We put
+        *          this here so we pre-allocate this once and can re-use
+        *          on every receive.
+        */
+       __u8 digest[SCTP_SIGNATURE_SIZE];
        /* sendbuf acct. policy.        */
        __u32 sndbuf_policy;
 
@@ -1499,9 +1508,9 @@ struct sctp_association {
         * These values will be initialized by system defaults, but can
         * be modified via the SCTP_RTOINFO socket option.
         */
-       __u32 rto_initial;
-       __u32 rto_max;
-       __u32 rto_min;
+       unsigned long rto_initial;
+       unsigned long rto_max;
+       unsigned long rto_min;
 
        /* Maximum number of new data packets that can be sent in a burst.  */
        int max_burst;
@@ -1519,13 +1528,13 @@ struct sctp_association {
        __u16 init_retries;
 
        /* The largest timeout or RTO value to use in attempting an INIT */
-       __u16 max_init_timeo;
+       unsigned long max_init_timeo;
 
        /* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
         * the destination address every heartbeat interval. This value
         * will be inherited by all new transports.
         */
-       __u32 hbinterval;
+       unsigned long hbinterval;
 
        /* This is the max_retrans value for new transports in the
         * association.
@@ -1537,13 +1546,14 @@ struct sctp_association {
         */
        __u32 pathmtu;
 
-       /* SACK delay timeout */
-       __u32 sackdelay;
-
        /* Flags controling Heartbeat, SACK delay, and Path MTU Discovery. */
        __u32 param_flags;
 
-       int timeouts[SCTP_NUM_TIMEOUT_TYPES];
+       /* SACK delay timeout */
+       unsigned long sackdelay;
+
+
+       unsigned long timeouts[SCTP_NUM_TIMEOUT_TYPES];
        struct timer_list timers[SCTP_NUM_TIMEOUT_TYPES];
 
        /* Transport to which SHUTDOWN chunk was last sent.  */
@@ -1648,7 +1658,10 @@ struct sctp_association {
        /* How many duplicated TSNs have we seen?  */
        int numduptsns;
 
-       /* Number of seconds of idle time before an association is closed.  */
+       /* Number of seconds of idle time before an association is closed.
+        * In the association context, this is really used as a boolean
+        * since the real timeout is stored in the timeouts array
+        */
        __u32 autoclose;
 
        /* These are to support
index 4aa6fc6..cb78b50 100644 (file)
@@ -257,20 +257,26 @@ int sctp_rcv(struct sk_buff *skb)
         */
        sctp_bh_lock_sock(sk);
 
+       /* It is possible that the association could have moved to a different
+        * socket if it is peeled off. If so, update the sk.
+        */ 
+       if (sk != rcvr->sk) {
+               sctp_bh_lock_sock(rcvr->sk);
+               sctp_bh_unlock_sock(sk);
+               sk = rcvr->sk;
+       }
+
        if (sock_owned_by_user(sk))
                sk_add_backlog(sk, skb);
        else
                sctp_backlog_rcv(sk, skb);
 
-       /* Release the sock and any reference counts we took in the
-        * lookup calls.
+       /* Release the sock and the sock ref we took in the lookup calls.
+        * The asoc/ep ref will be released in sctp_backlog_rcv.
         */
        sctp_bh_unlock_sock(sk);
-       if (asoc)
-               sctp_association_put(asoc);
-       else
-               sctp_endpoint_put(ep);
        sock_put(sk);
+
        return ret;
 
 discard_it:
@@ -296,12 +302,50 @@ discard_release:
 int sctp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
        struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
-       struct sctp_inq *inqueue = &chunk->rcvr->inqueue;
-
-       sctp_inq_push(inqueue, chunk);
+       struct sctp_inq *inqueue = NULL;
+       struct sctp_ep_common *rcvr = NULL;
+
+       rcvr = chunk->rcvr;
+
+       BUG_TRAP(rcvr->sk == sk);
+
+       if (rcvr->dead) {
+               sctp_chunk_free(chunk);
+       } else {
+               inqueue = &chunk->rcvr->inqueue;
+               sctp_inq_push(inqueue, chunk);
+       }
+
+       /* Release the asoc/ep ref we took in the lookup calls in sctp_rcv. */ 
+       if (SCTP_EP_TYPE_ASSOCIATION == rcvr->type)
+               sctp_association_put(sctp_assoc(rcvr));
+       else
+               sctp_endpoint_put(sctp_ep(rcvr));
+  
         return 0;
 }
 
+void sctp_backlog_migrate(struct sctp_association *assoc, 
+                         struct sock *oldsk, struct sock *newsk)
+{
+       struct sk_buff *skb;
+       struct sctp_chunk *chunk;
+
+       skb = oldsk->sk_backlog.head;
+       oldsk->sk_backlog.head = oldsk->sk_backlog.tail = NULL;
+       while (skb != NULL) {
+               struct sk_buff *next = skb->next;
+
+               chunk = SCTP_INPUT_CB(skb)->chunk;
+               skb->next = NULL;
+               if (&assoc->base == chunk->rcvr)
+                       sk_add_backlog(newsk, skb);
+               else
+                       sk_add_backlog(oldsk, skb);
+               skb = next;
+       }
+}
+
 /* Handle icmp frag needed error. */
 void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
                           struct sctp_transport *t, __u32 pmtu)
@@ -544,10 +588,16 @@ int sctp_rcv_ootb(struct sk_buff *skb)
        sctp_errhdr_t *err;
 
        ch = (sctp_chunkhdr_t *) skb->data;
-       ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
 
        /* Scan through all the chunks in the packet.  */
-       while (ch_end > (__u8 *)ch && ch_end < skb->tail) {
+       do {
+               /* Break out if chunk length is less then minimal. */
+               if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
+                       break;
+
+               ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+               if (ch_end > skb->tail)
+                       break;
 
                /* RFC 8.4, 2) If the OOTB packet contains an ABORT chunk, the
                 * receiver MUST silently discard the OOTB packet and take no
@@ -578,8 +628,7 @@ int sctp_rcv_ootb(struct sk_buff *skb)
                }
 
                ch = (sctp_chunkhdr_t *) ch_end;
-               ch_end = ((__u8 *) ch) + WORD_ROUND(ntohs(ch->length));
-       }
+       } while (ch_end < skb->tail);
 
        return 0;
 
index 2d33922..297b895 100644 (file)
@@ -73,8 +73,10 @@ void sctp_inq_free(struct sctp_inq *queue)
        /* If there is a packet which is currently being worked on,
         * free it as well.
         */
-       if (queue->in_progress)
+       if (queue->in_progress) {
                sctp_chunk_free(queue->in_progress);
+               queue->in_progress = NULL;
+       }
 
        if (queue->malloced) {
                /* Dump the master memory segment.  */
index 6e4dc28..d47a52c 100644 (file)
@@ -176,7 +176,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
 
 static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       if (*pos > sctp_ep_hashsize)
+       if (*pos >= sctp_ep_hashsize)
                return NULL;
 
        if (*pos < 0)
@@ -185,8 +185,6 @@ static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
        if (*pos == 0)
                seq_printf(seq, " ENDPT     SOCK   STY SST HBKT LPORT   UID INODE LADDRS\n");
 
-       ++*pos;
-
        return (void *)pos;
 }
 
@@ -198,11 +196,9 @@ static void sctp_eps_seq_stop(struct seq_file *seq, void *v)
 
 static void * sctp_eps_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       if (*pos > sctp_ep_hashsize)
+       if (++*pos >= sctp_ep_hashsize)
                return NULL;
 
-       ++*pos;
-
        return pos;
 }
 
@@ -214,19 +210,19 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v)
        struct sctp_ep_common *epb;
        struct sctp_endpoint *ep;
        struct sock *sk;
-       int    hash = *(int *)v;
+       int    hash = *(loff_t *)v;
 
-       if (hash > sctp_ep_hashsize)
+       if (hash >= sctp_ep_hashsize)
                return -ENOMEM;
 
-       head = &sctp_ep_hashtable[hash-1];
+       head = &sctp_ep_hashtable[hash];
        sctp_local_bh_disable();
        read_lock(&head->lock);
        for (epb = head->chain; epb; epb = epb->next) {
                ep = sctp_ep(epb);
                sk = epb->sk;
                seq_printf(seq, "%8p %8p %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk,
-                          sctp_sk(sk)->type, sk->sk_state, hash-1,
+                          sctp_sk(sk)->type, sk->sk_state, hash,
                           epb->bind_addr.port,
                           sock_i_uid(sk), sock_i_ino(sk));
 
@@ -283,7 +279,7 @@ void sctp_eps_proc_exit(void)
 
 static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
 {
-       if (*pos > sctp_assoc_hashsize)
+       if (*pos >= sctp_assoc_hashsize)
                return NULL;
 
        if (*pos < 0)
@@ -293,8 +289,6 @@ static void * sctp_assocs_seq_start(struct seq_file *seq, loff_t *pos)
                seq_printf(seq, " ASSOC     SOCK   STY SST ST HBKT ASSOC-ID TX_QUEUE RX_QUEUE UID INODE LPORT "
                                "RPORT LADDRS <-> RADDRS\n");
 
-       ++*pos;
-
        return (void *)pos;
 }
 
@@ -306,11 +300,9 @@ static void sctp_assocs_seq_stop(struct seq_file *seq, void *v)
 
 static void * sctp_assocs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-       if (*pos > sctp_assoc_hashsize)
+       if (++*pos >= sctp_assoc_hashsize)
                return NULL;
 
-       ++*pos;
-
        return pos;
 }
 
@@ -321,12 +313,12 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
        struct sctp_ep_common *epb;
        struct sctp_association *assoc;
        struct sock *sk;
-       int    hash = *(int *)v;
+       int    hash = *(loff_t *)v;
 
-       if (hash > sctp_assoc_hashsize)
+       if (hash >= sctp_assoc_hashsize)
                return -ENOMEM;
 
-       head = &sctp_assoc_hashtable[hash-1];
+       head = &sctp_assoc_hashtable[hash];
        sctp_local_bh_disable();
        read_lock(&head->lock);
        for (epb = head->chain; epb; epb = epb->next) {
@@ -335,7 +327,7 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v)
                seq_printf(seq,
                           "%8p %8p %-3d %-3d %-2d %-4d %4d %8d %8d %7d %5lu %-5d %5d ",
                           assoc, sk, sctp_sk(sk)->type, sk->sk_state,
-                          assoc->state, hash-1, assoc->assoc_id,
+                          assoc->state, hash, assoc->assoc_id,
                           (sk->sk_rcvbuf - assoc->rwnd),
                           assoc->sndbuf_used,
                           sock_i_uid(sk), sock_i_ino(sk),
index 556c495..5e0de3c 100644 (file)
@@ -1275,7 +1275,12 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
        unsigned int keylen;
        char *key;
 
-       headersize = sizeof(sctp_paramhdr_t) + SCTP_SECRET_SIZE;
+       /* Header size is static data prior to the actual cookie, including
+        * any padding.
+        */
+       headersize = sizeof(sctp_paramhdr_t) + 
+                    (sizeof(struct sctp_signed_cookie) - 
+                     sizeof(struct sctp_cookie));
        bodysize = sizeof(struct sctp_cookie)
                + ntohs(init_chunk->chunk_hdr->length) + addrs_len;
 
@@ -1354,7 +1359,7 @@ struct sctp_association *sctp_unpack_cookie(
        struct sctp_signed_cookie *cookie;
        struct sctp_cookie *bear_cookie;
        int headersize, bodysize, fixed_size;
-       __u8 digest[SCTP_SIGNATURE_SIZE];
+       __u8 *digest = ep->digest;
        struct scatterlist sg;
        unsigned int keylen, len;
        char *key;
@@ -1362,7 +1367,12 @@ struct sctp_association *sctp_unpack_cookie(
        struct sk_buff *skb = chunk->skb;
        struct timeval tv;
 
-       headersize = sizeof(sctp_chunkhdr_t) + SCTP_SECRET_SIZE;
+       /* Header size is static data prior to the actual cookie, including
+        * any padding.
+        */
+       headersize = sizeof(sctp_chunkhdr_t) +
+                    (sizeof(struct sctp_signed_cookie) - 
+                     sizeof(struct sctp_cookie));
        bodysize = ntohs(chunk->chunk_hdr->length) - headersize;
        fixed_size = headersize + sizeof(struct sctp_cookie);
 
index b8b38ab..8d1dc24 100644 (file)
@@ -1300,7 +1300,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                        "T1 INIT Timeout adjustment"
                                        " init_err_counter: %d"
                                        " cycle: %d"
-                                       " timeout: %d\n",
+                                       " timeout: %ld\n",
                                        asoc->init_err_counter,
                                        asoc->init_cycle,
                                        asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_INIT]);
@@ -1328,7 +1328,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        SCTP_DEBUG_PRINTK(
                                "T1 COOKIE Timeout adjustment"
                                " init_err_counter: %d"
-                               " timeout: %d\n",
+                               " timeout: %ld\n",
                                asoc->init_err_counter,
                                asoc->timeouts[SCTP_EVENT_TIMEOUT_T1_COOKIE]);
 
index 477d7f8..71c9a96 100644 (file)
@@ -3090,6 +3090,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
                        break;
 
                ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
+               if (ch_end > skb->tail)
+                       break;
 
                if (SCTP_CID_SHUTDOWN_ACK == ch->type)
                        ootb_shut_ack = 1;
index c98ee37..fb1821d 100644 (file)
@@ -2995,7 +2995,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
        sp->hbinterval  = jiffies_to_msecs(sctp_hb_interval);
        sp->pathmaxrxt  = sctp_max_retrans_path;
        sp->pathmtu     = 0; // allow default discovery
-       sp->sackdelay   = sctp_sack_timeout;
+       sp->sackdelay   = jiffies_to_msecs(sctp_sack_timeout);
        sp->param_flags = SPP_HB_ENABLE |
                          SPP_PMTUD_ENABLE |
                          SPP_SACKDELAY_ENABLE;
@@ -5602,8 +5602,12 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
         */
        newsp->type = type;
 
+       spin_lock_bh(&oldsk->sk_lock.slock);
+       /* Migrate the backlog from oldsk to newsk. */
+       sctp_backlog_migrate(assoc, oldsk, newsk);
        /* Migrate the association to the new socket. */
        sctp_assoc_migrate(assoc, newsk);
+       spin_unlock_bh(&oldsk->sk_lock.slock);
 
        /* If the association on the newsk is already closed before accept()
         * is called, set RCV_SHUTDOWN flag.
index fcd7096..dc6f3ff 100644 (file)
@@ -159,12 +159,9 @@ static ctl_table sctp_table[] = {
                .ctl_name       = NET_SCTP_PRESERVE_ENABLE,
                .procname       = "cookie_preserve_enable",
                .data           = &sctp_cookie_preserve_enable,
-               .maxlen         = sizeof(long),
+               .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = &proc_doulongvec_ms_jiffies_minmax,
-               .strategy       = &sctp_sysctl_jiffies_ms,
-               .extra1         = &rto_timer_min,
-               .extra2         = &rto_timer_max
+               .proc_handler   = &proc_dointvec
        },
        {
                .ctl_name       = NET_SCTP_RTO_ALPHA,
index 68d73e2..160f62a 100644 (file)
@@ -350,7 +350,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
        tp->rto_pending = 0;
 
        SCTP_DEBUG_PRINTK("%s: transport: %p, rtt: %d, srtt: %d "
-                         "rttvar: %d, rto: %d\n", __FUNCTION__,
+                         "rttvar: %d, rto: %ld\n", __FUNCTION__,
                          tp, rtt, tp->srtt, tp->rttvar, tp->rto);
 }