Home | History | Annotate | Line # | Download | only in netinet
sctputil.c revision 1.12.12.2
      1  1.12.12.2  jdolecek /*	$KAME: sctputil.c,v 1.39 2005/06/16 20:54:06 jinmei Exp $	*/
      2  1.12.12.2  jdolecek /*	$NetBSD: sctputil.c,v 1.12.12.2 2017/12/03 11:39:04 jdolecek Exp $	*/
      3  1.12.12.2  jdolecek 
      4  1.12.12.2  jdolecek /*
      5  1.12.12.2  jdolecek  * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
      6  1.12.12.2  jdolecek  * All rights reserved.
      7  1.12.12.2  jdolecek  *
      8  1.12.12.2  jdolecek  * Redistribution and use in source and binary forms, with or without
      9  1.12.12.2  jdolecek  * modification, are permitted provided that the following conditions
     10  1.12.12.2  jdolecek  * are met:
     11  1.12.12.2  jdolecek  * 1. Redistributions of source code must retain the above copyright
     12  1.12.12.2  jdolecek  *    notice, this list of conditions and the following disclaimer.
     13  1.12.12.2  jdolecek  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.12.12.2  jdolecek  *    notice, this list of conditions and the following disclaimer in the
     15  1.12.12.2  jdolecek  *    documentation and/or other materials provided with the distribution.
     16  1.12.12.2  jdolecek  * 3. All advertising materials mentioning features or use of this software
     17  1.12.12.2  jdolecek  *    must display the following acknowledgement:
     18  1.12.12.2  jdolecek  *      This product includes software developed by Cisco Systems, Inc.
     19  1.12.12.2  jdolecek  * 4. Neither the name of the project nor the names of its contributors
     20  1.12.12.2  jdolecek  *    may be used to endorse or promote products derived from this software
     21  1.12.12.2  jdolecek  *    without specific prior written permission.
     22  1.12.12.2  jdolecek  *
     23  1.12.12.2  jdolecek  * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
     24  1.12.12.2  jdolecek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  1.12.12.2  jdolecek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  1.12.12.2  jdolecek  * ARE DISCLAIMED.  IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
     27  1.12.12.2  jdolecek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  1.12.12.2  jdolecek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  1.12.12.2  jdolecek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  1.12.12.2  jdolecek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  1.12.12.2  jdolecek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  1.12.12.2  jdolecek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  1.12.12.2  jdolecek  * SUCH DAMAGE.
     34  1.12.12.2  jdolecek  */
     35  1.12.12.2  jdolecek 
     36  1.12.12.2  jdolecek #include <sys/cdefs.h>
     37  1.12.12.2  jdolecek __KERNEL_RCSID(0, "$NetBSD: sctputil.c,v 1.12.12.2 2017/12/03 11:39:04 jdolecek Exp $");
     38  1.12.12.2  jdolecek 
     39  1.12.12.2  jdolecek #ifdef _KERNEL_OPT
     40  1.12.12.2  jdolecek #include "opt_inet.h"
     41  1.12.12.2  jdolecek #include "opt_ipsec.h"
     42  1.12.12.2  jdolecek #include "opt_sctp.h"
     43  1.12.12.2  jdolecek #endif /* _KERNEL_OPT */
     44  1.12.12.2  jdolecek 
     45  1.12.12.2  jdolecek #include <sys/param.h>
     46  1.12.12.2  jdolecek #include <sys/systm.h>
     47  1.12.12.2  jdolecek #include <sys/malloc.h>
     48  1.12.12.2  jdolecek #include <sys/mbuf.h>
     49  1.12.12.2  jdolecek #include <sys/domain.h>
     50  1.12.12.2  jdolecek #include <sys/protosw.h>
     51  1.12.12.2  jdolecek #include <sys/socket.h>
     52  1.12.12.2  jdolecek #include <sys/socketvar.h>
     53  1.12.12.2  jdolecek #include <sys/mutex.h>
     54  1.12.12.2  jdolecek #include <sys/proc.h>
     55  1.12.12.2  jdolecek #include <sys/kernel.h>
     56  1.12.12.2  jdolecek #include <sys/sysctl.h>
     57  1.12.12.2  jdolecek 
     58  1.12.12.2  jdolecek #include <sys/callout.h>
     59  1.12.12.2  jdolecek 
     60  1.12.12.2  jdolecek #include <net/route.h>
     61  1.12.12.2  jdolecek 
     62  1.12.12.2  jdolecek #ifdef INET6
     63  1.12.12.2  jdolecek #include <sys/domain.h>
     64  1.12.12.2  jdolecek #endif
     65  1.12.12.2  jdolecek 
     66  1.12.12.2  jdolecek #include <machine/limits.h>
     67  1.12.12.2  jdolecek 
     68  1.12.12.2  jdolecek #include <net/if.h>
     69  1.12.12.2  jdolecek #include <net/if_types.h>
     70  1.12.12.2  jdolecek #include <net/route.h>
     71  1.12.12.2  jdolecek 
     72  1.12.12.2  jdolecek #include <netinet/in.h>
     73  1.12.12.2  jdolecek #include <netinet/in_systm.h>
     74  1.12.12.2  jdolecek #include <netinet/ip.h>
     75  1.12.12.2  jdolecek #include <netinet/in_pcb.h>
     76  1.12.12.2  jdolecek #include <netinet/in_var.h>
     77  1.12.12.2  jdolecek #include <netinet/ip_var.h>
     78  1.12.12.2  jdolecek 
     79  1.12.12.2  jdolecek #ifdef INET6
     80  1.12.12.2  jdolecek #include <netinet/ip6.h>
     81  1.12.12.2  jdolecek #include <netinet6/ip6_var.h>
     82  1.12.12.2  jdolecek #include <netinet6/scope6_var.h>
     83  1.12.12.2  jdolecek #include <netinet6/in6_pcb.h>
     84  1.12.12.2  jdolecek 
     85  1.12.12.2  jdolecek #endif /* INET6 */
     86  1.12.12.2  jdolecek 
     87  1.12.12.2  jdolecek #include <netinet/sctp_pcb.h>
     88  1.12.12.2  jdolecek 
     89  1.12.12.2  jdolecek #ifdef IPSEC
     90  1.12.12.2  jdolecek #include <netipsec/ipsec.h>
     91  1.12.12.2  jdolecek #include <netipsec/key.h>
     92  1.12.12.2  jdolecek #endif /* IPSEC */
     93  1.12.12.2  jdolecek 
     94  1.12.12.2  jdolecek #include <netinet/sctputil.h>
     95  1.12.12.2  jdolecek #include <netinet/sctp_var.h>
     96  1.12.12.2  jdolecek #ifdef INET6
     97  1.12.12.2  jdolecek #include <netinet6/sctp6_var.h>
     98  1.12.12.2  jdolecek #endif
     99  1.12.12.2  jdolecek #include <netinet/sctp_header.h>
    100  1.12.12.2  jdolecek #include <netinet/sctp_output.h>
    101  1.12.12.2  jdolecek #include <netinet/sctp_hashdriver.h>
    102  1.12.12.2  jdolecek #include <netinet/sctp_uio.h>
    103  1.12.12.2  jdolecek #include <netinet/sctp_timer.h>
    104  1.12.12.2  jdolecek #include <netinet/sctp_crc32.h>
    105  1.12.12.2  jdolecek #include <netinet/sctp_indata.h>	/* for sctp_deliver_data() */
    106  1.12.12.2  jdolecek #define NUMBER_OF_MTU_SIZES 18
    107  1.12.12.2  jdolecek 
    108  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
    109  1.12.12.2  jdolecek extern u_int32_t sctp_debug_on;
    110  1.12.12.2  jdolecek #endif
    111  1.12.12.2  jdolecek 
    112  1.12.12.2  jdolecek #ifdef SCTP_STAT_LOGGING
    113  1.12.12.2  jdolecek int sctp_cwnd_log_at=0;
    114  1.12.12.2  jdolecek int sctp_cwnd_log_rolled=0;
    115  1.12.12.2  jdolecek struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE];
    116  1.12.12.2  jdolecek 
    117  1.12.12.2  jdolecek void sctp_clr_stat_log(void)
    118  1.12.12.2  jdolecek {
    119  1.12.12.2  jdolecek 	sctp_cwnd_log_at=0;
    120  1.12.12.2  jdolecek 	sctp_cwnd_log_rolled=0;
    121  1.12.12.2  jdolecek }
    122  1.12.12.2  jdolecek 
    123  1.12.12.2  jdolecek void
    124  1.12.12.2  jdolecek sctp_log_strm_del_alt(u_int32_t tsn, u_int16_t sseq, int from)
    125  1.12.12.2  jdolecek {
    126  1.12.12.2  jdolecek 
    127  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    128  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_STRM;
    129  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.strlog.n_tsn = tsn;
    130  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.strlog.n_sseq = sseq;
    131  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn = 0;
    132  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq = 0;
    133  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    134  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    135  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    136  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    137  1.12.12.2  jdolecek 	}
    138  1.12.12.2  jdolecek 
    139  1.12.12.2  jdolecek }
    140  1.12.12.2  jdolecek 
    141  1.12.12.2  jdolecek void
    142  1.12.12.2  jdolecek sctp_log_map(uint32_t map, uint32_t cum, uint32_t high, int from)
    143  1.12.12.2  jdolecek {
    144  1.12.12.2  jdolecek 
    145  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    146  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAP;
    147  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.map.base = map;
    148  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.map.cum = cum;
    149  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.map.high = high;
    150  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    151  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    152  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    153  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    154  1.12.12.2  jdolecek 	}
    155  1.12.12.2  jdolecek }
    156  1.12.12.2  jdolecek 
    157  1.12.12.2  jdolecek void
    158  1.12.12.2  jdolecek sctp_log_fr(uint32_t biggest_tsn, uint32_t biggest_new_tsn, uint32_t tsn,
    159  1.12.12.2  jdolecek     int from)
    160  1.12.12.2  jdolecek {
    161  1.12.12.2  jdolecek 
    162  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    163  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_FR;
    164  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.fr.largest_tsn = biggest_tsn;
    165  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.fr.largest_new_tsn = biggest_new_tsn;
    166  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.fr.tsn = tsn;
    167  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    168  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    169  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    170  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    171  1.12.12.2  jdolecek 	}
    172  1.12.12.2  jdolecek }
    173  1.12.12.2  jdolecek 
    174  1.12.12.2  jdolecek void
    175  1.12.12.2  jdolecek sctp_log_strm_del(struct sctp_tmit_chunk *chk, struct sctp_tmit_chunk *poschk,
    176  1.12.12.2  jdolecek     int from)
    177  1.12.12.2  jdolecek {
    178  1.12.12.2  jdolecek 
    179  1.12.12.2  jdolecek 	if (chk == NULL) {
    180  1.12.12.2  jdolecek 		printf("Gak log of NULL?\n");
    181  1.12.12.2  jdolecek 		return;
    182  1.12.12.2  jdolecek 	}
    183  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    184  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_STRM;
    185  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.strlog.n_tsn = chk->rec.data.TSN_seq;
    186  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.strlog.n_sseq = chk->rec.data.stream_seq;
    187  1.12.12.2  jdolecek 	if (poschk != NULL) {
    188  1.12.12.2  jdolecek 		sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn =
    189  1.12.12.2  jdolecek 		    poschk->rec.data.TSN_seq;
    190  1.12.12.2  jdolecek 		sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq =
    191  1.12.12.2  jdolecek 		    poschk->rec.data.stream_seq;
    192  1.12.12.2  jdolecek 	} else {
    193  1.12.12.2  jdolecek 		sctp_clog[sctp_cwnd_log_at].x.strlog.e_tsn = 0;
    194  1.12.12.2  jdolecek 		sctp_clog[sctp_cwnd_log_at].x.strlog.e_sseq = 0;
    195  1.12.12.2  jdolecek 	}
    196  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    197  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    198  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    199  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    200  1.12.12.2  jdolecek 	}
    201  1.12.12.2  jdolecek }
    202  1.12.12.2  jdolecek 
    203  1.12.12.2  jdolecek void
    204  1.12.12.2  jdolecek sctp_log_cwnd(struct sctp_nets *net, int augment, uint8_t from)
    205  1.12.12.2  jdolecek {
    206  1.12.12.2  jdolecek 
    207  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    208  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_CWND;
    209  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
    210  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = net->cwnd;
    211  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
    212  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = augment;
    213  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    214  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    215  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    216  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    217  1.12.12.2  jdolecek 	}
    218  1.12.12.2  jdolecek }
    219  1.12.12.2  jdolecek 
    220  1.12.12.2  jdolecek void
    221  1.12.12.2  jdolecek sctp_log_maxburst(struct sctp_nets *net, int error, int burst, uint8_t from)
    222  1.12.12.2  jdolecek {
    223  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    224  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MAXBURST;
    225  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.net = net;
    226  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_new_value = error;
    227  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.inflight = net->flight_size;
    228  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.cwnd.cwnd_augment = burst;
    229  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    230  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    231  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    232  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    233  1.12.12.2  jdolecek 	}
    234  1.12.12.2  jdolecek }
    235  1.12.12.2  jdolecek 
    236  1.12.12.2  jdolecek void
    237  1.12.12.2  jdolecek sctp_log_rwnd(uint8_t from, u_int32_t peers_rwnd , u_int32_t snd_size, u_int32_t overhead)
    238  1.12.12.2  jdolecek {
    239  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    240  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
    241  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
    242  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = snd_size;
    243  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
    244  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = 0;
    245  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    246  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    247  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    248  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    249  1.12.12.2  jdolecek 	}
    250  1.12.12.2  jdolecek }
    251  1.12.12.2  jdolecek 
    252  1.12.12.2  jdolecek void
    253  1.12.12.2  jdolecek sctp_log_rwnd_set(uint8_t from, u_int32_t peers_rwnd , u_int32_t flight_size, u_int32_t overhead, u_int32_t a_rwndval)
    254  1.12.12.2  jdolecek {
    255  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    256  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_RWND;
    257  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.rwnd = peers_rwnd;
    258  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.send_size = flight_size;
    259  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.overhead = overhead;
    260  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.rwnd.new_rwnd = a_rwndval;
    261  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    262  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    263  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    264  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    265  1.12.12.2  jdolecek 	}
    266  1.12.12.2  jdolecek }
    267  1.12.12.2  jdolecek 
    268  1.12.12.2  jdolecek void
    269  1.12.12.2  jdolecek sctp_log_mbcnt(uint8_t from, u_int32_t total_oq , u_int32_t book, u_int32_t total_mbcnt_q, u_int32_t mbcnt)
    270  1.12.12.2  jdolecek {
    271  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    272  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_MBCNT;
    273  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_size = total_oq;
    274  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.mbcnt.size_change  = book;
    275  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.mbcnt.total_queue_mb_size = total_mbcnt_q;
    276  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.mbcnt.mbcnt_change = mbcnt;
    277  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    278  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    279  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    280  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    281  1.12.12.2  jdolecek 	}
    282  1.12.12.2  jdolecek }
    283  1.12.12.2  jdolecek 
    284  1.12.12.2  jdolecek void
    285  1.12.12.2  jdolecek sctp_log_block(uint8_t from, struct socket *so, struct sctp_association *asoc)
    286  1.12.12.2  jdolecek {
    287  1.12.12.2  jdolecek 
    288  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].from = (u_int8_t)from;
    289  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].event_type = (u_int8_t)SCTP_LOG_EVENT_BLOCK;
    290  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.blk.maxmb = (u_int16_t)(so->so_snd.sb_mbmax/1024);
    291  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.blk.onmb = asoc->total_output_mbuf_queue_size;
    292  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.blk.maxsb = (u_int16_t)(so->so_snd.sb_hiwat/1024);
    293  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.blk.onsb = asoc->total_output_queue_size;
    294  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.blk.send_sent_qcnt = (u_int16_t)(asoc->send_queue_cnt + asoc->sent_queue_cnt);
    295  1.12.12.2  jdolecek 	sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (u_int16_t)asoc->stream_queue_cnt;
    296  1.12.12.2  jdolecek 	sctp_cwnd_log_at++;
    297  1.12.12.2  jdolecek 	if (sctp_cwnd_log_at >= SCTP_STAT_LOG_SIZE) {
    298  1.12.12.2  jdolecek 		sctp_cwnd_log_at = 0;
    299  1.12.12.2  jdolecek 		sctp_cwnd_log_rolled = 1;
    300  1.12.12.2  jdolecek 	}
    301  1.12.12.2  jdolecek }
    302  1.12.12.2  jdolecek 
    303  1.12.12.2  jdolecek int
    304  1.12.12.2  jdolecek sctp_fill_stat_log(struct mbuf *m)
    305  1.12.12.2  jdolecek {
    306  1.12.12.2  jdolecek 	struct sctp_cwnd_log_req *req;
    307  1.12.12.2  jdolecek 	int size_limit, num, i, at, cnt_out=0;
    308  1.12.12.2  jdolecek 
    309  1.12.12.2  jdolecek 	if (m == NULL)
    310  1.12.12.2  jdolecek 		return (EINVAL);
    311  1.12.12.2  jdolecek 
    312  1.12.12.2  jdolecek 	size_limit = (m->m_len - sizeof(struct sctp_cwnd_log_req));
    313  1.12.12.2  jdolecek 	if (size_limit < sizeof(struct sctp_cwnd_log)) {
    314  1.12.12.2  jdolecek 		return (EINVAL);
    315  1.12.12.2  jdolecek 	}
    316  1.12.12.2  jdolecek 	req = mtod(m, struct sctp_cwnd_log_req *);
    317  1.12.12.2  jdolecek 	num = size_limit/sizeof(struct sctp_cwnd_log);
    318  1.12.12.2  jdolecek 	if (sctp_cwnd_log_rolled) {
    319  1.12.12.2  jdolecek 		req->num_in_log = SCTP_STAT_LOG_SIZE;
    320  1.12.12.2  jdolecek 	} else {
    321  1.12.12.2  jdolecek 		req->num_in_log = sctp_cwnd_log_at;
    322  1.12.12.2  jdolecek 		/* if the log has not rolled, we don't
    323  1.12.12.2  jdolecek 		 * let you have old data.
    324  1.12.12.2  jdolecek 		 */
    325  1.12.12.2  jdolecek  		if (req->end_at > sctp_cwnd_log_at) {
    326  1.12.12.2  jdolecek 			req->end_at = sctp_cwnd_log_at;
    327  1.12.12.2  jdolecek 		}
    328  1.12.12.2  jdolecek 	}
    329  1.12.12.2  jdolecek 	if ((num < SCTP_STAT_LOG_SIZE) &&
    330  1.12.12.2  jdolecek 	    ((sctp_cwnd_log_rolled) || (sctp_cwnd_log_at > num))) {
    331  1.12.12.2  jdolecek 		/* we can't return all of it */
    332  1.12.12.2  jdolecek 		if (((req->start_at == 0) && (req->end_at == 0)) ||
    333  1.12.12.2  jdolecek 		    (req->start_at >= SCTP_STAT_LOG_SIZE) ||
    334  1.12.12.2  jdolecek 		    (req->end_at >= SCTP_STAT_LOG_SIZE)) {
    335  1.12.12.2  jdolecek 			/* No user request or user is wacked. */
    336  1.12.12.2  jdolecek 			req->num_ret = num;
    337  1.12.12.2  jdolecek 			req->end_at = sctp_cwnd_log_at - 1;
    338  1.12.12.2  jdolecek 			if ((sctp_cwnd_log_at - num) < 0) {
    339  1.12.12.2  jdolecek 				int cc;
    340  1.12.12.2  jdolecek 				cc = num - sctp_cwnd_log_at;
    341  1.12.12.2  jdolecek 				req->start_at = SCTP_STAT_LOG_SIZE - cc;
    342  1.12.12.2  jdolecek 			} else {
    343  1.12.12.2  jdolecek 				req->start_at = sctp_cwnd_log_at - num;
    344  1.12.12.2  jdolecek 			}
    345  1.12.12.2  jdolecek 		} else {
    346  1.12.12.2  jdolecek 			/* a user request */
    347  1.12.12.2  jdolecek 			int cc;
    348  1.12.12.2  jdolecek 			if (req->start_at > req->end_at) {
    349  1.12.12.2  jdolecek 				cc = (SCTP_STAT_LOG_SIZE - req->start_at) +
    350  1.12.12.2  jdolecek 				    (req->end_at + 1);
    351  1.12.12.2  jdolecek 			} else {
    352  1.12.12.2  jdolecek 
    353  1.12.12.2  jdolecek 				cc = req->end_at - req->start_at;
    354  1.12.12.2  jdolecek 			}
    355  1.12.12.2  jdolecek 			if (cc < num) {
    356  1.12.12.2  jdolecek 				num = cc;
    357  1.12.12.2  jdolecek 			}
    358  1.12.12.2  jdolecek 			req->num_ret = num;
    359  1.12.12.2  jdolecek 		}
    360  1.12.12.2  jdolecek 	} else {
    361  1.12.12.2  jdolecek 		/* We can return all  of it */
    362  1.12.12.2  jdolecek 		req->start_at = 0;
    363  1.12.12.2  jdolecek 		req->end_at = sctp_cwnd_log_at - 1;
    364  1.12.12.2  jdolecek 		req->num_ret = sctp_cwnd_log_at;
    365  1.12.12.2  jdolecek 	}
    366  1.12.12.2  jdolecek 	for (i = 0, at = req->start_at; i < req->num_ret; i++) {
    367  1.12.12.2  jdolecek 		req->log[i] = sctp_clog[at];
    368  1.12.12.2  jdolecek 		cnt_out++;
    369  1.12.12.2  jdolecek 		at++;
    370  1.12.12.2  jdolecek 		if (at >= SCTP_STAT_LOG_SIZE)
    371  1.12.12.2  jdolecek 			at = 0;
    372  1.12.12.2  jdolecek 	}
    373  1.12.12.2  jdolecek 	m->m_len = (cnt_out * sizeof(struct sctp_cwnd_log_req)) + sizeof(struct sctp_cwnd_log_req);
    374  1.12.12.2  jdolecek 	return (0);
    375  1.12.12.2  jdolecek }
    376  1.12.12.2  jdolecek 
    377  1.12.12.2  jdolecek #endif
    378  1.12.12.2  jdolecek 
    379  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
    380  1.12.12.2  jdolecek u_int8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
    381  1.12.12.2  jdolecek static int sctp_audit_indx = 0;
    382  1.12.12.2  jdolecek 
    383  1.12.12.2  jdolecek static
    384  1.12.12.2  jdolecek void sctp_print_audit_report(void)
    385  1.12.12.2  jdolecek {
    386  1.12.12.2  jdolecek 	int i;
    387  1.12.12.2  jdolecek 	int cnt;
    388  1.12.12.2  jdolecek 	cnt = 0;
    389  1.12.12.2  jdolecek 	for (i=sctp_audit_indx;i<SCTP_AUDIT_SIZE;i++) {
    390  1.12.12.2  jdolecek 		if ((sctp_audit_data[i][0] == 0xe0) &&
    391  1.12.12.2  jdolecek 		    (sctp_audit_data[i][1] == 0x01)) {
    392  1.12.12.2  jdolecek 			cnt = 0;
    393  1.12.12.2  jdolecek 			printf("\n");
    394  1.12.12.2  jdolecek 		} else if (sctp_audit_data[i][0] == 0xf0) {
    395  1.12.12.2  jdolecek 			cnt = 0;
    396  1.12.12.2  jdolecek 			printf("\n");
    397  1.12.12.2  jdolecek 		} else if ((sctp_audit_data[i][0] == 0xc0) &&
    398  1.12.12.2  jdolecek 		    (sctp_audit_data[i][1] == 0x01)) {
    399  1.12.12.2  jdolecek 			printf("\n");
    400  1.12.12.2  jdolecek 			cnt = 0;
    401  1.12.12.2  jdolecek 		}
    402  1.12.12.2  jdolecek 		printf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
    403  1.12.12.2  jdolecek 		    (uint32_t)sctp_audit_data[i][1]);
    404  1.12.12.2  jdolecek 		cnt++;
    405  1.12.12.2  jdolecek 		if ((cnt % 14) == 0)
    406  1.12.12.2  jdolecek 			printf("\n");
    407  1.12.12.2  jdolecek 	}
    408  1.12.12.2  jdolecek 	for (i=0;i<sctp_audit_indx;i++) {
    409  1.12.12.2  jdolecek 		if ((sctp_audit_data[i][0] == 0xe0) &&
    410  1.12.12.2  jdolecek 		    (sctp_audit_data[i][1] == 0x01)) {
    411  1.12.12.2  jdolecek 			cnt = 0;
    412  1.12.12.2  jdolecek 			printf("\n");
    413  1.12.12.2  jdolecek 		} else if (sctp_audit_data[i][0] == 0xf0) {
    414  1.12.12.2  jdolecek 			cnt = 0;
    415  1.12.12.2  jdolecek 			printf("\n");
    416  1.12.12.2  jdolecek 		} else if ((sctp_audit_data[i][0] == 0xc0) &&
    417  1.12.12.2  jdolecek 			 (sctp_audit_data[i][1] == 0x01)) {
    418  1.12.12.2  jdolecek 			printf("\n");
    419  1.12.12.2  jdolecek 			cnt = 0;
    420  1.12.12.2  jdolecek 		}
    421  1.12.12.2  jdolecek 		printf("%2.2x%2.2x ", (uint32_t)sctp_audit_data[i][0],
    422  1.12.12.2  jdolecek 		    (uint32_t)sctp_audit_data[i][1]);
    423  1.12.12.2  jdolecek 		cnt++;
    424  1.12.12.2  jdolecek 		if ((cnt % 14) == 0)
    425  1.12.12.2  jdolecek 			printf("\n");
    426  1.12.12.2  jdolecek 	}
    427  1.12.12.2  jdolecek 	printf("\n");
    428  1.12.12.2  jdolecek }
    429  1.12.12.2  jdolecek 
    430  1.12.12.2  jdolecek void sctp_auditing(int from, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
    431  1.12.12.2  jdolecek     struct sctp_nets *net)
    432  1.12.12.2  jdolecek {
    433  1.12.12.2  jdolecek 	int resend_cnt, tot_out, rep, tot_book_cnt;
    434  1.12.12.2  jdolecek 	struct sctp_nets *lnet;
    435  1.12.12.2  jdolecek 	struct sctp_tmit_chunk *chk;
    436  1.12.12.2  jdolecek 
    437  1.12.12.2  jdolecek 	sctp_audit_data[sctp_audit_indx][0] = 0xAA;
    438  1.12.12.2  jdolecek 	sctp_audit_data[sctp_audit_indx][1] = 0x000000ff & from;
    439  1.12.12.2  jdolecek 	sctp_audit_indx++;
    440  1.12.12.2  jdolecek 	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    441  1.12.12.2  jdolecek 		sctp_audit_indx = 0;
    442  1.12.12.2  jdolecek 	}
    443  1.12.12.2  jdolecek 	if (inp == NULL) {
    444  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
    445  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][1] = 0x01;
    446  1.12.12.2  jdolecek 		sctp_audit_indx++;
    447  1.12.12.2  jdolecek 		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    448  1.12.12.2  jdolecek 			sctp_audit_indx = 0;
    449  1.12.12.2  jdolecek 		}
    450  1.12.12.2  jdolecek 		return;
    451  1.12.12.2  jdolecek 	}
    452  1.12.12.2  jdolecek 	if (stcb == NULL) {
    453  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
    454  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][1] = 0x02;
    455  1.12.12.2  jdolecek 		sctp_audit_indx++;
    456  1.12.12.2  jdolecek 		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    457  1.12.12.2  jdolecek 			sctp_audit_indx = 0;
    458  1.12.12.2  jdolecek 		}
    459  1.12.12.2  jdolecek 		return;
    460  1.12.12.2  jdolecek 	}
    461  1.12.12.2  jdolecek 	sctp_audit_data[sctp_audit_indx][0] = 0xA1;
    462  1.12.12.2  jdolecek 	sctp_audit_data[sctp_audit_indx][1] =
    463  1.12.12.2  jdolecek 	    (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
    464  1.12.12.2  jdolecek 	sctp_audit_indx++;
    465  1.12.12.2  jdolecek 	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    466  1.12.12.2  jdolecek 		sctp_audit_indx = 0;
    467  1.12.12.2  jdolecek 	}
    468  1.12.12.2  jdolecek 	rep = 0;
    469  1.12.12.2  jdolecek 	tot_book_cnt = 0;
    470  1.12.12.2  jdolecek 	resend_cnt = tot_out = 0;
    471  1.12.12.2  jdolecek 	TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
    472  1.12.12.2  jdolecek 		if (chk->sent == SCTP_DATAGRAM_RESEND) {
    473  1.12.12.2  jdolecek 			resend_cnt++;
    474  1.12.12.2  jdolecek 		} else if (chk->sent < SCTP_DATAGRAM_RESEND) {
    475  1.12.12.2  jdolecek 			tot_out += chk->book_size;
    476  1.12.12.2  jdolecek 			tot_book_cnt++;
    477  1.12.12.2  jdolecek 		}
    478  1.12.12.2  jdolecek 	}
    479  1.12.12.2  jdolecek 	if (resend_cnt != stcb->asoc.sent_queue_retran_cnt) {
    480  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
    481  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][1] = 0xA1;
    482  1.12.12.2  jdolecek 		sctp_audit_indx++;
    483  1.12.12.2  jdolecek 		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    484  1.12.12.2  jdolecek 			sctp_audit_indx = 0;
    485  1.12.12.2  jdolecek 		}
    486  1.12.12.2  jdolecek 		printf("resend_cnt:%d asoc-tot:%d\n",
    487  1.12.12.2  jdolecek 		    resend_cnt, stcb->asoc.sent_queue_retran_cnt);
    488  1.12.12.2  jdolecek 		rep = 1;
    489  1.12.12.2  jdolecek 		stcb->asoc.sent_queue_retran_cnt = resend_cnt;
    490  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][0] = 0xA2;
    491  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][1] =
    492  1.12.12.2  jdolecek 		    (0x000000ff & stcb->asoc.sent_queue_retran_cnt);
    493  1.12.12.2  jdolecek 		sctp_audit_indx++;
    494  1.12.12.2  jdolecek 		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    495  1.12.12.2  jdolecek 			sctp_audit_indx = 0;
    496  1.12.12.2  jdolecek 		}
    497  1.12.12.2  jdolecek 	}
    498  1.12.12.2  jdolecek 	if (tot_out != stcb->asoc.total_flight) {
    499  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
    500  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][1] = 0xA2;
    501  1.12.12.2  jdolecek 		sctp_audit_indx++;
    502  1.12.12.2  jdolecek 		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    503  1.12.12.2  jdolecek 			sctp_audit_indx = 0;
    504  1.12.12.2  jdolecek 		}
    505  1.12.12.2  jdolecek 		rep = 1;
    506  1.12.12.2  jdolecek 		printf("tot_flt:%d asoc_tot:%d\n", tot_out,
    507  1.12.12.2  jdolecek 		    (int)stcb->asoc.total_flight);
    508  1.12.12.2  jdolecek 		stcb->asoc.total_flight = tot_out;
    509  1.12.12.2  jdolecek 	}
    510  1.12.12.2  jdolecek 	if (tot_book_cnt != stcb->asoc.total_flight_count) {
    511  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
    512  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][1] = 0xA5;
    513  1.12.12.2  jdolecek 		sctp_audit_indx++;
    514  1.12.12.2  jdolecek 		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    515  1.12.12.2  jdolecek 			sctp_audit_indx = 0;
    516  1.12.12.2  jdolecek 		}
    517  1.12.12.2  jdolecek 		rep = 1;
    518  1.12.12.2  jdolecek 		printf("tot_flt_book:%d\n", tot_book);
    519  1.12.12.2  jdolecek 
    520  1.12.12.2  jdolecek 		stcb->asoc.total_flight_count = tot_book_cnt;
    521  1.12.12.2  jdolecek 	}
    522  1.12.12.2  jdolecek 	tot_out = 0;
    523  1.12.12.2  jdolecek 	TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
    524  1.12.12.2  jdolecek 		tot_out += lnet->flight_size;
    525  1.12.12.2  jdolecek 	}
    526  1.12.12.2  jdolecek 	if (tot_out != stcb->asoc.total_flight) {
    527  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][0] = 0xAF;
    528  1.12.12.2  jdolecek 		sctp_audit_data[sctp_audit_indx][1] = 0xA3;
    529  1.12.12.2  jdolecek 		sctp_audit_indx++;
    530  1.12.12.2  jdolecek 		if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    531  1.12.12.2  jdolecek 			sctp_audit_indx = 0;
    532  1.12.12.2  jdolecek 		}
    533  1.12.12.2  jdolecek 		rep = 1;
    534  1.12.12.2  jdolecek 		printf("real flight:%d net total was %d\n",
    535  1.12.12.2  jdolecek 		    stcb->asoc.total_flight, tot_out);
    536  1.12.12.2  jdolecek 		/* now corrective action */
    537  1.12.12.2  jdolecek 		TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
    538  1.12.12.2  jdolecek 			tot_out = 0;
    539  1.12.12.2  jdolecek 			TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
    540  1.12.12.2  jdolecek 				if ((chk->whoTo == lnet) &&
    541  1.12.12.2  jdolecek 				    (chk->sent < SCTP_DATAGRAM_RESEND)) {
    542  1.12.12.2  jdolecek 					tot_out += chk->book_size;
    543  1.12.12.2  jdolecek 				}
    544  1.12.12.2  jdolecek 			}
    545  1.12.12.2  jdolecek 			if (lnet->flight_size != tot_out) {
    546  1.12.12.2  jdolecek 				printf("net:%x flight was %d corrected to %d\n",
    547  1.12.12.2  jdolecek 				    (uint32_t)lnet, lnet->flight_size, tot_out);
    548  1.12.12.2  jdolecek 				lnet->flight_size = tot_out;
    549  1.12.12.2  jdolecek 			}
    550  1.12.12.2  jdolecek 
    551  1.12.12.2  jdolecek 		}
    552  1.12.12.2  jdolecek 	}
    553  1.12.12.2  jdolecek 
    554  1.12.12.2  jdolecek 	if (rep) {
    555  1.12.12.2  jdolecek 		sctp_print_audit_report();
    556  1.12.12.2  jdolecek 	}
    557  1.12.12.2  jdolecek }
    558  1.12.12.2  jdolecek 
    559  1.12.12.2  jdolecek void
    560  1.12.12.2  jdolecek sctp_audit_log(u_int8_t ev, u_int8_t fd)
    561  1.12.12.2  jdolecek {
    562  1.12.12.2  jdolecek 	sctp_audit_data[sctp_audit_indx][0] = ev;
    563  1.12.12.2  jdolecek 	sctp_audit_data[sctp_audit_indx][1] = fd;
    564  1.12.12.2  jdolecek 	sctp_audit_indx++;
    565  1.12.12.2  jdolecek 	if (sctp_audit_indx >= SCTP_AUDIT_SIZE) {
    566  1.12.12.2  jdolecek 		sctp_audit_indx = 0;
    567  1.12.12.2  jdolecek 	}
    568  1.12.12.2  jdolecek }
    569  1.12.12.2  jdolecek 
    570  1.12.12.2  jdolecek #endif
    571  1.12.12.2  jdolecek 
    572  1.12.12.2  jdolecek /*
    573  1.12.12.2  jdolecek  * a list of sizes based on typical mtu's, used only if next hop
    574  1.12.12.2  jdolecek  * size not returned.
    575  1.12.12.2  jdolecek  */
    576  1.12.12.2  jdolecek static int sctp_mtu_sizes[] = {
    577  1.12.12.2  jdolecek 	68,
    578  1.12.12.2  jdolecek 	296,
    579  1.12.12.2  jdolecek 	508,
    580  1.12.12.2  jdolecek 	512,
    581  1.12.12.2  jdolecek 	544,
    582  1.12.12.2  jdolecek 	576,
    583  1.12.12.2  jdolecek 	1006,
    584  1.12.12.2  jdolecek 	1492,
    585  1.12.12.2  jdolecek 	1500,
    586  1.12.12.2  jdolecek 	1536,
    587  1.12.12.2  jdolecek 	2002,
    588  1.12.12.2  jdolecek 	2048,
    589  1.12.12.2  jdolecek 	4352,
    590  1.12.12.2  jdolecek 	4464,
    591  1.12.12.2  jdolecek 	8166,
    592  1.12.12.2  jdolecek 	17914,
    593  1.12.12.2  jdolecek 	32000,
    594  1.12.12.2  jdolecek 	65535
    595  1.12.12.2  jdolecek };
    596  1.12.12.2  jdolecek 
    597  1.12.12.2  jdolecek int
    598  1.12.12.2  jdolecek find_next_best_mtu(int totsz)
    599  1.12.12.2  jdolecek {
    600  1.12.12.2  jdolecek 	int i, perfer;
    601  1.12.12.2  jdolecek 	/*
    602  1.12.12.2  jdolecek 	 * if we are in here we must find the next best fit based on the
    603  1.12.12.2  jdolecek 	 * size of the dg that failed to be sent.
    604  1.12.12.2  jdolecek 	 */
    605  1.12.12.2  jdolecek 	perfer = 0;
    606  1.12.12.2  jdolecek 	for (i = 0; i < NUMBER_OF_MTU_SIZES; i++) {
    607  1.12.12.2  jdolecek 		if (totsz < sctp_mtu_sizes[i]) {
    608  1.12.12.2  jdolecek 			perfer = i - 1;
    609  1.12.12.2  jdolecek 			if (perfer < 0)
    610  1.12.12.2  jdolecek 				perfer = 0;
    611  1.12.12.2  jdolecek 			break;
    612  1.12.12.2  jdolecek 		}
    613  1.12.12.2  jdolecek 	}
    614  1.12.12.2  jdolecek 	return (sctp_mtu_sizes[perfer]);
    615  1.12.12.2  jdolecek }
    616  1.12.12.2  jdolecek 
    617  1.12.12.2  jdolecek void
    618  1.12.12.2  jdolecek sctp_fill_random_store(struct sctp_pcb *m)
    619  1.12.12.2  jdolecek {
    620  1.12.12.2  jdolecek 	/*
    621  1.12.12.2  jdolecek 	 * Here we use the MD5/SHA-1 to hash with our good randomNumbers
    622  1.12.12.2  jdolecek 	 * and our counter. The result becomes our good random numbers and
    623  1.12.12.2  jdolecek 	 * we then setup to give these out. Note that we do no lockig
    624  1.12.12.2  jdolecek 	 * to protect this. This is ok, since if competing folks call
    625  1.12.12.2  jdolecek 	 * this we will get more gobbled gook in the random store whic
    626  1.12.12.2  jdolecek 	 * is what we want. There is a danger that two guys will use
    627  1.12.12.2  jdolecek 	 * the same random numbers, but thats ok too since that
    628  1.12.12.2  jdolecek 	 * is random as well :->
    629  1.12.12.2  jdolecek 	 */
    630  1.12.12.2  jdolecek 	m->store_at = 0;
    631  1.12.12.2  jdolecek 	sctp_hash_digest((char *)m->random_numbers, sizeof(m->random_numbers),
    632  1.12.12.2  jdolecek 			 (char *)&m->random_counter, sizeof(m->random_counter),
    633  1.12.12.2  jdolecek 			 (char *)m->random_store);
    634  1.12.12.2  jdolecek 	m->random_counter++;
    635  1.12.12.2  jdolecek }
    636  1.12.12.2  jdolecek 
    637  1.12.12.2  jdolecek uint32_t
    638  1.12.12.2  jdolecek sctp_select_initial_TSN(struct sctp_pcb *m)
    639  1.12.12.2  jdolecek {
    640  1.12.12.2  jdolecek 	/*
    641  1.12.12.2  jdolecek 	 * A true implementation should use random selection process to
    642  1.12.12.2  jdolecek 	 * get the initial stream sequence number, using RFC1750 as a
    643  1.12.12.2  jdolecek 	 * good guideline
    644  1.12.12.2  jdolecek 	 */
    645  1.12.12.2  jdolecek 	u_long x, *xp;
    646  1.12.12.2  jdolecek 	uint8_t *p;
    647  1.12.12.2  jdolecek 
    648  1.12.12.2  jdolecek 	if (m->initial_sequence_debug != 0) {
    649  1.12.12.2  jdolecek 		u_int32_t ret;
    650  1.12.12.2  jdolecek 		ret = m->initial_sequence_debug;
    651  1.12.12.2  jdolecek 		m->initial_sequence_debug++;
    652  1.12.12.2  jdolecek 		return (ret);
    653  1.12.12.2  jdolecek 	}
    654  1.12.12.2  jdolecek 	if ((m->store_at+sizeof(u_long)) > SCTP_SIGNATURE_SIZE) {
    655  1.12.12.2  jdolecek 		/* Refill the random store */
    656  1.12.12.2  jdolecek 		sctp_fill_random_store(m);
    657  1.12.12.2  jdolecek 	}
    658  1.12.12.2  jdolecek 	p = &m->random_store[(int)m->store_at];
    659  1.12.12.2  jdolecek 	xp = (u_long *)p;
    660  1.12.12.2  jdolecek 	x = *xp;
    661  1.12.12.2  jdolecek 	m->store_at += sizeof(u_long);
    662  1.12.12.2  jdolecek 	return (x);
    663  1.12.12.2  jdolecek }
    664  1.12.12.2  jdolecek 
    665  1.12.12.2  jdolecek u_int32_t sctp_select_a_tag(struct sctp_inpcb *m)
    666  1.12.12.2  jdolecek {
    667  1.12.12.2  jdolecek 	u_long x, not_done;
    668  1.12.12.2  jdolecek 	struct timeval now;
    669  1.12.12.2  jdolecek 
    670  1.12.12.2  jdolecek 	SCTP_GETTIME_TIMEVAL(&now);
    671  1.12.12.2  jdolecek 	not_done = 1;
    672  1.12.12.2  jdolecek 	while (not_done) {
    673  1.12.12.2  jdolecek 		x = sctp_select_initial_TSN(&m->sctp_ep);
    674  1.12.12.2  jdolecek 		if (x == 0) {
    675  1.12.12.2  jdolecek 			/* we never use 0 */
    676  1.12.12.2  jdolecek 			continue;
    677  1.12.12.2  jdolecek 		}
    678  1.12.12.2  jdolecek 		if (sctp_is_vtag_good(m, x, &now)) {
    679  1.12.12.2  jdolecek 			not_done = 0;
    680  1.12.12.2  jdolecek 		}
    681  1.12.12.2  jdolecek 	}
    682  1.12.12.2  jdolecek 	return (x);
    683  1.12.12.2  jdolecek }
    684  1.12.12.2  jdolecek 
    685  1.12.12.2  jdolecek 
    686  1.12.12.2  jdolecek int
    687  1.12.12.2  jdolecek sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
    688  1.12.12.2  jdolecek 	       int for_a_init, uint32_t override_tag )
    689  1.12.12.2  jdolecek {
    690  1.12.12.2  jdolecek 	/*
    691  1.12.12.2  jdolecek 	 * Anything set to zero is taken care of by the allocation
    692  1.12.12.2  jdolecek 	 * routine's bzero
    693  1.12.12.2  jdolecek 	 */
    694  1.12.12.2  jdolecek 
    695  1.12.12.2  jdolecek 	/*
    696  1.12.12.2  jdolecek 	 * Up front select what scoping to apply on addresses I tell my peer
    697  1.12.12.2  jdolecek 	 * Not sure what to do with these right now, we will need to come up
    698  1.12.12.2  jdolecek 	 * with a way to set them. We may need to pass them through from the
    699  1.12.12.2  jdolecek 	 * caller in the sctp_aloc_assoc() function.
    700  1.12.12.2  jdolecek 	 */
    701  1.12.12.2  jdolecek 	int i;
    702  1.12.12.2  jdolecek 	/* init all variables to a known value.*/
    703  1.12.12.2  jdolecek 	asoc->state = SCTP_STATE_INUSE;
    704  1.12.12.2  jdolecek 	asoc->max_burst = m->sctp_ep.max_burst;
    705  1.12.12.2  jdolecek 	asoc->heart_beat_delay = m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT];
    706  1.12.12.2  jdolecek 	asoc->cookie_life = m->sctp_ep.def_cookie_life;
    707  1.12.12.2  jdolecek 
    708  1.12.12.2  jdolecek 	if (override_tag) {
    709  1.12.12.2  jdolecek 		asoc->my_vtag = override_tag;
    710  1.12.12.2  jdolecek 	} else {
    711  1.12.12.2  jdolecek 		asoc->my_vtag = sctp_select_a_tag(m);
    712  1.12.12.2  jdolecek 	}
    713  1.12.12.2  jdolecek 	asoc->asconf_seq_out = asoc->str_reset_seq_out = asoc->init_seq_number = asoc->sending_seq =
    714  1.12.12.2  jdolecek 		sctp_select_initial_TSN(&m->sctp_ep);
    715  1.12.12.2  jdolecek 	asoc->t3timeout_highest_marked = asoc->asconf_seq_out;
    716  1.12.12.2  jdolecek 	/* we are opptimisitic here */
    717  1.12.12.2  jdolecek 	asoc->peer_supports_asconf = 1;
    718  1.12.12.2  jdolecek 	asoc->peer_supports_asconf_setprim = 1;
    719  1.12.12.2  jdolecek 	asoc->peer_supports_pktdrop = 1;
    720  1.12.12.2  jdolecek 
    721  1.12.12.2  jdolecek 	asoc->sent_queue_retran_cnt = 0;
    722  1.12.12.2  jdolecek 	/* This will need to be adjusted */
    723  1.12.12.2  jdolecek 	asoc->last_cwr_tsn = asoc->init_seq_number - 1;
    724  1.12.12.2  jdolecek 	asoc->last_acked_seq = asoc->init_seq_number - 1;
    725  1.12.12.2  jdolecek 	asoc->advanced_peer_ack_point = asoc->last_acked_seq;
    726  1.12.12.2  jdolecek 	asoc->asconf_seq_in = asoc->last_acked_seq;
    727  1.12.12.2  jdolecek 
    728  1.12.12.2  jdolecek 	/* here we are different, we hold the next one we expect */
    729  1.12.12.2  jdolecek 	asoc->str_reset_seq_in = asoc->last_acked_seq + 1;
    730  1.12.12.2  jdolecek 
    731  1.12.12.2  jdolecek 	asoc->initial_init_rto_max = m->sctp_ep.initial_init_rto_max;
    732  1.12.12.2  jdolecek 	asoc->initial_rto = m->sctp_ep.initial_rto;
    733  1.12.12.2  jdolecek 
    734  1.12.12.2  jdolecek 	asoc->max_init_times = m->sctp_ep.max_init_times;
    735  1.12.12.2  jdolecek 	asoc->max_send_times = m->sctp_ep.max_send_times;
    736  1.12.12.2  jdolecek 	asoc->def_net_failure = m->sctp_ep.def_net_failure;
    737  1.12.12.2  jdolecek 
    738  1.12.12.2  jdolecek 	/* ECN Nonce initialization */
    739  1.12.12.2  jdolecek 	asoc->ecn_nonce_allowed = 0;
    740  1.12.12.2  jdolecek 	asoc->receiver_nonce_sum = 1;
    741  1.12.12.2  jdolecek 	asoc->nonce_sum_expect_base = 1;
    742  1.12.12.2  jdolecek 	asoc->nonce_sum_check = 1;
    743  1.12.12.2  jdolecek 	asoc->nonce_resync_tsn = 0;
    744  1.12.12.2  jdolecek 	asoc->nonce_wait_for_ecne = 0;
    745  1.12.12.2  jdolecek 	asoc->nonce_wait_tsn = 0;
    746  1.12.12.2  jdolecek 
    747  1.12.12.2  jdolecek 	if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
    748  1.12.12.2  jdolecek 		struct in6pcb *inp6;
    749  1.12.12.2  jdolecek 
    750  1.12.12.2  jdolecek 
    751  1.12.12.2  jdolecek 		/* Its a V6 socket */
    752  1.12.12.2  jdolecek 		inp6 = (struct in6pcb *)m;
    753  1.12.12.2  jdolecek 		asoc->ipv6_addr_legal = 1;
    754  1.12.12.2  jdolecek 		/* Now look at the binding flag to see if V4 will be legal */
    755  1.12.12.2  jdolecek 	if (
    756  1.12.12.2  jdolecek #if defined(__OpenBSD__)
    757  1.12.12.2  jdolecek 		(0) /* we always do dual bind */
    758  1.12.12.2  jdolecek #elif defined (__NetBSD__)
    759  1.12.12.2  jdolecek 		(inp6->in6p_flags & IN6P_IPV6_V6ONLY)
    760  1.12.12.2  jdolecek #else
    761  1.12.12.2  jdolecek 		(inp6->inp_flags & IN6P_IPV6_V6ONLY)
    762  1.12.12.2  jdolecek #endif
    763  1.12.12.2  jdolecek 	     == 0) {
    764  1.12.12.2  jdolecek 			asoc->ipv4_addr_legal = 1;
    765  1.12.12.2  jdolecek 		} else {
    766  1.12.12.2  jdolecek 			/* V4 addresses are NOT legal on the association */
    767  1.12.12.2  jdolecek 			asoc->ipv4_addr_legal = 0;
    768  1.12.12.2  jdolecek 		}
    769  1.12.12.2  jdolecek 	} else {
    770  1.12.12.2  jdolecek 		/* Its a V4 socket, no - V6 */
    771  1.12.12.2  jdolecek 		asoc->ipv4_addr_legal = 1;
    772  1.12.12.2  jdolecek 		asoc->ipv6_addr_legal = 0;
    773  1.12.12.2  jdolecek 	}
    774  1.12.12.2  jdolecek 
    775  1.12.12.2  jdolecek 
    776  1.12.12.2  jdolecek 	asoc->my_rwnd = max(m->sctp_socket->so_rcv.sb_hiwat, SCTP_MINIMAL_RWND);
    777  1.12.12.2  jdolecek 	asoc->peers_rwnd = m->sctp_socket->so_rcv.sb_hiwat;
    778  1.12.12.2  jdolecek 
    779  1.12.12.2  jdolecek 	asoc->smallest_mtu = m->sctp_frag_point;
    780  1.12.12.2  jdolecek 	asoc->minrto = m->sctp_ep.sctp_minrto;
    781  1.12.12.2  jdolecek 	asoc->maxrto = m->sctp_ep.sctp_maxrto;
    782  1.12.12.2  jdolecek 
    783  1.12.12.2  jdolecek 	LIST_INIT(&asoc->sctp_local_addr_list);
    784  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->nets);
    785  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->pending_reply_queue);
    786  1.12.12.2  jdolecek 	asoc->last_asconf_ack_sent = NULL;
    787  1.12.12.2  jdolecek 	/* Setup to fill the hb random cache at first HB */
    788  1.12.12.2  jdolecek 	asoc->hb_random_idx = 4;
    789  1.12.12.2  jdolecek 
    790  1.12.12.2  jdolecek 	asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
    791  1.12.12.2  jdolecek 
    792  1.12.12.2  jdolecek 	/*
    793  1.12.12.2  jdolecek 	 * Now the stream parameters, here we allocate space for all
    794  1.12.12.2  jdolecek 	 * streams that we request by default.
    795  1.12.12.2  jdolecek 	 */
    796  1.12.12.2  jdolecek 	asoc->streamoutcnt = asoc->pre_open_streams =
    797  1.12.12.2  jdolecek 	    m->sctp_ep.pre_open_stream_count;
    798  1.12.12.2  jdolecek 	asoc->strmout = malloc(asoc->streamoutcnt *
    799  1.12.12.2  jdolecek 	    sizeof(struct sctp_stream_out), M_PCB, M_NOWAIT);
    800  1.12.12.2  jdolecek 	if (asoc->strmout == NULL) {
    801  1.12.12.2  jdolecek 		/* big trouble no memory */
    802  1.12.12.2  jdolecek 		return (ENOMEM);
    803  1.12.12.2  jdolecek 	}
    804  1.12.12.2  jdolecek 	for (i = 0; i < asoc->streamoutcnt; i++) {
    805  1.12.12.2  jdolecek 		/*
    806  1.12.12.2  jdolecek 		 * inbound side must be set to 0xffff,
    807  1.12.12.2  jdolecek 		 * also NOTE when we get the INIT-ACK back (for INIT sender)
    808  1.12.12.2  jdolecek 		 * we MUST reduce the count (streamoutcnt) but first check
    809  1.12.12.2  jdolecek 		 * if we sent to any of the upper streams that were dropped
    810  1.12.12.2  jdolecek 		 * (if some were). Those that were dropped must be notified
    811  1.12.12.2  jdolecek 		 * to the upper layer as failed to send.
    812  1.12.12.2  jdolecek 		 */
    813  1.12.12.2  jdolecek 		asoc->strmout[i].next_sequence_sent = 0x0;
    814  1.12.12.2  jdolecek 		TAILQ_INIT(&asoc->strmout[i].outqueue);
    815  1.12.12.2  jdolecek 		asoc->strmout[i].stream_no = i;
    816  1.12.12.2  jdolecek 		asoc->strmout[i].next_spoke.tqe_next = 0;
    817  1.12.12.2  jdolecek 		asoc->strmout[i].next_spoke.tqe_prev = 0;
    818  1.12.12.2  jdolecek 	}
    819  1.12.12.2  jdolecek 	/* Now the mapping array */
    820  1.12.12.2  jdolecek 	asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
    821  1.12.12.2  jdolecek 	asoc->mapping_array = malloc(asoc->mapping_array_size,
    822  1.12.12.2  jdolecek 	       M_PCB, M_NOWAIT);
    823  1.12.12.2  jdolecek 	if (asoc->mapping_array == NULL) {
    824  1.12.12.2  jdolecek 		free(asoc->strmout, M_PCB);
    825  1.12.12.2  jdolecek 		return (ENOMEM);
    826  1.12.12.2  jdolecek 	}
    827  1.12.12.2  jdolecek 	memset(asoc->mapping_array, 0, asoc->mapping_array_size);
    828  1.12.12.2  jdolecek 	/* Now the init of the other outqueues */
    829  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->out_wheel);
    830  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->control_send_queue);
    831  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->send_queue);
    832  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->sent_queue);
    833  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->reasmqueue);
    834  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->delivery_queue);
    835  1.12.12.2  jdolecek 	asoc->max_inbound_streams = m->sctp_ep.max_open_streams_intome;
    836  1.12.12.2  jdolecek 
    837  1.12.12.2  jdolecek 	TAILQ_INIT(&asoc->asconf_queue);
    838  1.12.12.2  jdolecek 	return (0);
    839  1.12.12.2  jdolecek }
    840  1.12.12.2  jdolecek 
    841  1.12.12.2  jdolecek int
    842  1.12.12.2  jdolecek sctp_expand_mapping_array(struct sctp_association *asoc)
    843  1.12.12.2  jdolecek {
    844  1.12.12.2  jdolecek 	/* mapping array needs to grow */
    845  1.12.12.2  jdolecek 	u_int8_t *new_array;
    846  1.12.12.2  jdolecek 	uint16_t new_size, old_size;
    847  1.12.12.2  jdolecek 
    848  1.12.12.2  jdolecek 	old_size = asoc->mapping_array_size;
    849  1.12.12.2  jdolecek 	new_size = old_size + SCTP_MAPPING_ARRAY_INCR;
    850  1.12.12.2  jdolecek 	new_array = malloc(new_size, M_PCB, M_NOWAIT);
    851  1.12.12.2  jdolecek 	if (new_array == NULL) {
    852  1.12.12.2  jdolecek 		/* can't get more, forget it */
    853  1.12.12.2  jdolecek 		printf("No memory for expansion of SCTP mapping array %d\n",
    854  1.12.12.2  jdolecek 		       new_size);
    855  1.12.12.2  jdolecek 		return (-1);
    856  1.12.12.2  jdolecek 	}
    857  1.12.12.2  jdolecek 	memcpy(new_array, asoc->mapping_array, old_size);
    858  1.12.12.2  jdolecek 	memset(new_array + old_size, 0, SCTP_MAPPING_ARRAY_INCR);
    859  1.12.12.2  jdolecek 	free(asoc->mapping_array, M_PCB);
    860  1.12.12.2  jdolecek 	asoc->mapping_array = new_array;
    861  1.12.12.2  jdolecek 	asoc->mapping_array_size = new_size;
    862  1.12.12.2  jdolecek 	return (0);
    863  1.12.12.2  jdolecek }
    864  1.12.12.2  jdolecek 
    865  1.12.12.2  jdolecek static void
    866  1.12.12.2  jdolecek sctp_timeout_handler(void *t)
    867  1.12.12.2  jdolecek {
    868  1.12.12.2  jdolecek 	struct sctp_inpcb *inp;
    869  1.12.12.2  jdolecek 	struct sctp_tcb *stcb;
    870  1.12.12.2  jdolecek 	struct sctp_nets *net;
    871  1.12.12.2  jdolecek 	struct sctp_timer *tmr;
    872  1.12.12.2  jdolecek 	int did_output;
    873  1.12.12.2  jdolecek 
    874  1.12.12.2  jdolecek 	mutex_enter(softnet_lock);
    875  1.12.12.2  jdolecek 	tmr = (struct sctp_timer *)t;
    876  1.12.12.2  jdolecek 	inp = (struct sctp_inpcb *)tmr->ep;
    877  1.12.12.2  jdolecek 	stcb = (struct sctp_tcb *)tmr->tcb;
    878  1.12.12.2  jdolecek 	net = (struct sctp_nets *)tmr->net;
    879  1.12.12.2  jdolecek 	did_output = 1;
    880  1.12.12.2  jdolecek 
    881  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
    882  1.12.12.2  jdolecek 	sctp_audit_log(0xF0, (u_int8_t)tmr->type);
    883  1.12.12.2  jdolecek 	sctp_auditing(3, inp, stcb, net);
    884  1.12.12.2  jdolecek #endif
    885  1.12.12.2  jdolecek 	sctp_pegs[SCTP_TIMERS_EXP]++;
    886  1.12.12.2  jdolecek 
    887  1.12.12.2  jdolecek 	if (inp == NULL) {
    888  1.12.12.2  jdolecek 		return;
    889  1.12.12.2  jdolecek 	}
    890  1.12.12.2  jdolecek 
    891  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(inp);
    892  1.12.12.2  jdolecek 	if (inp->sctp_socket == 0) {
    893  1.12.12.2  jdolecek 		mutex_exit(softnet_lock);
    894  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(inp);
    895  1.12.12.2  jdolecek 		return;
    896  1.12.12.2  jdolecek 	}
    897  1.12.12.2  jdolecek 	if (stcb) {
    898  1.12.12.2  jdolecek 		if (stcb->asoc.state == 0) {
    899  1.12.12.2  jdolecek 			mutex_exit(softnet_lock);
    900  1.12.12.2  jdolecek 			SCTP_INP_WUNLOCK(inp);
    901  1.12.12.2  jdolecek 			return;
    902  1.12.12.2  jdolecek 		}
    903  1.12.12.2  jdolecek 	}
    904  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
    905  1.12.12.2  jdolecek 	if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
    906  1.12.12.2  jdolecek 		printf("Timer type %d goes off\n", tmr->type);
    907  1.12.12.2  jdolecek 	}
    908  1.12.12.2  jdolecek #endif /* SCTP_DEBUG */
    909  1.12.12.2  jdolecek #ifndef __NetBSD__
    910  1.12.12.2  jdolecek 	if (!callout_active(&tmr->timer)) {
    911  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(inp);
    912  1.12.12.2  jdolecek 		return;
    913  1.12.12.2  jdolecek 	}
    914  1.12.12.2  jdolecek #endif
    915  1.12.12.2  jdolecek 	if (stcb) {
    916  1.12.12.2  jdolecek 		SCTP_TCB_LOCK(stcb);
    917  1.12.12.2  jdolecek 	}
    918  1.12.12.2  jdolecek 	SCTP_INP_INCR_REF(inp);
    919  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(inp);
    920  1.12.12.2  jdolecek 
    921  1.12.12.2  jdolecek 	switch (tmr->type) {
    922  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_ITERATOR:
    923  1.12.12.2  jdolecek 	{
    924  1.12.12.2  jdolecek 		struct sctp_iterator *it;
    925  1.12.12.2  jdolecek 		it = (struct sctp_iterator *)inp;
    926  1.12.12.2  jdolecek 		sctp_iterator_timer(it);
    927  1.12.12.2  jdolecek 	}
    928  1.12.12.2  jdolecek 	break;
    929  1.12.12.2  jdolecek 	/* call the handler for the appropriate timer type */
    930  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SEND:
    931  1.12.12.2  jdolecek 		sctp_pegs[SCTP_TMIT_TIMER]++;
    932  1.12.12.2  jdolecek 		stcb->asoc.num_send_timers_up--;
    933  1.12.12.2  jdolecek 		if (stcb->asoc.num_send_timers_up < 0) {
    934  1.12.12.2  jdolecek 			stcb->asoc.num_send_timers_up = 0;
    935  1.12.12.2  jdolecek 		}
    936  1.12.12.2  jdolecek 		if (sctp_t3rxt_timer(inp, stcb, net)) {
    937  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
    938  1.12.12.2  jdolecek 
    939  1.12.12.2  jdolecek 			goto out_decr;
    940  1.12.12.2  jdolecek 		}
    941  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
    942  1.12.12.2  jdolecek 		sctp_auditing(4, inp, stcb, net);
    943  1.12.12.2  jdolecek #endif
    944  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 1);
    945  1.12.12.2  jdolecek 		if ((stcb->asoc.num_send_timers_up == 0) &&
    946  1.12.12.2  jdolecek 		    (stcb->asoc.sent_queue_cnt > 0)
    947  1.12.12.2  jdolecek 			) {
    948  1.12.12.2  jdolecek 			struct sctp_tmit_chunk *chk;
    949  1.12.12.2  jdolecek 			/*
    950  1.12.12.2  jdolecek 			 * safeguard. If there on some on the sent queue
    951  1.12.12.2  jdolecek 			 * somewhere but no timers running something is
    952  1.12.12.2  jdolecek 			 * wrong... so we start a timer on the first chunk
    953  1.12.12.2  jdolecek 			 * on the send queue on whatever net it is sent to.
    954  1.12.12.2  jdolecek 			 */
    955  1.12.12.2  jdolecek 			sctp_pegs[SCTP_T3_SAFEGRD]++;
    956  1.12.12.2  jdolecek 			chk = TAILQ_FIRST(&stcb->asoc.sent_queue);
    957  1.12.12.2  jdolecek 			sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb,
    958  1.12.12.2  jdolecek 					 chk->whoTo);
    959  1.12.12.2  jdolecek 		}
    960  1.12.12.2  jdolecek 		break;
    961  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_INIT:
    962  1.12.12.2  jdolecek 		if (sctp_t1init_timer(inp, stcb, net)) {
    963  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
    964  1.12.12.2  jdolecek 			goto out_decr;
    965  1.12.12.2  jdolecek 		}
    966  1.12.12.2  jdolecek 		/* We do output but not here */
    967  1.12.12.2  jdolecek 		did_output = 0;
    968  1.12.12.2  jdolecek 		break;
    969  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_RECV:
    970  1.12.12.2  jdolecek 		sctp_pegs[SCTP_RECV_TIMER]++;
    971  1.12.12.2  jdolecek 		sctp_send_sack(stcb);
    972  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
    973  1.12.12.2  jdolecek 		sctp_auditing(4, inp, stcb, net);
    974  1.12.12.2  jdolecek #endif
    975  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 4);
    976  1.12.12.2  jdolecek 		break;
    977  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWN:
    978  1.12.12.2  jdolecek 		if (sctp_shutdown_timer(inp, stcb, net) ) {
    979  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
    980  1.12.12.2  jdolecek 			goto out_decr;
    981  1.12.12.2  jdolecek 		}
    982  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
    983  1.12.12.2  jdolecek 		sctp_auditing(4, inp, stcb, net);
    984  1.12.12.2  jdolecek #endif
    985  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 5);
    986  1.12.12.2  jdolecek 		break;
    987  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_HEARTBEAT:
    988  1.12.12.2  jdolecek 		if (sctp_heartbeat_timer(inp, stcb, net)) {
    989  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
    990  1.12.12.2  jdolecek 			goto out_decr;
    991  1.12.12.2  jdolecek 		}
    992  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
    993  1.12.12.2  jdolecek 		sctp_auditing(4, inp, stcb, net);
    994  1.12.12.2  jdolecek #endif
    995  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 6);
    996  1.12.12.2  jdolecek 		break;
    997  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_COOKIE:
    998  1.12.12.2  jdolecek 		if (sctp_cookie_timer(inp, stcb, net)) {
    999  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
   1000  1.12.12.2  jdolecek 			goto out_decr;
   1001  1.12.12.2  jdolecek 		}
   1002  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
   1003  1.12.12.2  jdolecek 		sctp_auditing(4, inp, stcb, net);
   1004  1.12.12.2  jdolecek #endif
   1005  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 1);
   1006  1.12.12.2  jdolecek 		break;
   1007  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_NEWCOOKIE:
   1008  1.12.12.2  jdolecek 	{
   1009  1.12.12.2  jdolecek 		struct timeval tv;
   1010  1.12.12.2  jdolecek 		int i, secret;
   1011  1.12.12.2  jdolecek 		SCTP_GETTIME_TIMEVAL(&tv);
   1012  1.12.12.2  jdolecek 		SCTP_INP_WLOCK(inp);
   1013  1.12.12.2  jdolecek 		inp->sctp_ep.time_of_secret_change = tv.tv_sec;
   1014  1.12.12.2  jdolecek 		inp->sctp_ep.last_secret_number =
   1015  1.12.12.2  jdolecek 			inp->sctp_ep.current_secret_number;
   1016  1.12.12.2  jdolecek 		inp->sctp_ep.current_secret_number++;
   1017  1.12.12.2  jdolecek 		if (inp->sctp_ep.current_secret_number >=
   1018  1.12.12.2  jdolecek 		    SCTP_HOW_MANY_SECRETS) {
   1019  1.12.12.2  jdolecek 			inp->sctp_ep.current_secret_number = 0;
   1020  1.12.12.2  jdolecek 		}
   1021  1.12.12.2  jdolecek 		secret = (int)inp->sctp_ep.current_secret_number;
   1022  1.12.12.2  jdolecek 		for (i = 0; i < SCTP_NUMBER_OF_SECRETS; i++) {
   1023  1.12.12.2  jdolecek 			inp->sctp_ep.secret_key[secret][i] =
   1024  1.12.12.2  jdolecek 				sctp_select_initial_TSN(&inp->sctp_ep);
   1025  1.12.12.2  jdolecek 		}
   1026  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(inp);
   1027  1.12.12.2  jdolecek 		sctp_timer_start(SCTP_TIMER_TYPE_NEWCOOKIE, inp, stcb, net);
   1028  1.12.12.2  jdolecek 	}
   1029  1.12.12.2  jdolecek 	did_output = 0;
   1030  1.12.12.2  jdolecek 	break;
   1031  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_PATHMTURAISE:
   1032  1.12.12.2  jdolecek 		sctp_pathmtu_timer(inp, stcb, net);
   1033  1.12.12.2  jdolecek 		did_output = 0;
   1034  1.12.12.2  jdolecek 		break;
   1035  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWNACK:
   1036  1.12.12.2  jdolecek 		if (sctp_shutdownack_timer(inp, stcb, net)) {
   1037  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
   1038  1.12.12.2  jdolecek 			goto out_decr;
   1039  1.12.12.2  jdolecek 		}
   1040  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
   1041  1.12.12.2  jdolecek 		sctp_auditing(4, inp, stcb, net);
   1042  1.12.12.2  jdolecek #endif
   1043  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 7);
   1044  1.12.12.2  jdolecek 		break;
   1045  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
   1046  1.12.12.2  jdolecek 		sctp_abort_an_association(inp, stcb,
   1047  1.12.12.2  jdolecek 					  SCTP_SHUTDOWN_GUARD_EXPIRES, NULL);
   1048  1.12.12.2  jdolecek 		/* no need to unlock on tcb its gone */
   1049  1.12.12.2  jdolecek 		goto out_decr;
   1050  1.12.12.2  jdolecek 		break;
   1051  1.12.12.2  jdolecek 
   1052  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_STRRESET:
   1053  1.12.12.2  jdolecek 		if (sctp_strreset_timer(inp, stcb, net)) {
   1054  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
   1055  1.12.12.2  jdolecek 			goto out_decr;
   1056  1.12.12.2  jdolecek 		}
   1057  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 9);
   1058  1.12.12.2  jdolecek 		break;
   1059  1.12.12.2  jdolecek 
   1060  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_ASCONF:
   1061  1.12.12.2  jdolecek 		if (sctp_asconf_timer(inp, stcb, net)) {
   1062  1.12.12.2  jdolecek 			/* no need to unlock on tcb its gone */
   1063  1.12.12.2  jdolecek 			goto out_decr;
   1064  1.12.12.2  jdolecek 		}
   1065  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
   1066  1.12.12.2  jdolecek 		sctp_auditing(4, inp, stcb, net);
   1067  1.12.12.2  jdolecek #endif
   1068  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 8);
   1069  1.12.12.2  jdolecek 		break;
   1070  1.12.12.2  jdolecek 
   1071  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_AUTOCLOSE:
   1072  1.12.12.2  jdolecek 		sctp_autoclose_timer(inp, stcb, net);
   1073  1.12.12.2  jdolecek 		sctp_chunk_output(inp, stcb, 10);
   1074  1.12.12.2  jdolecek 		did_output = 0;
   1075  1.12.12.2  jdolecek 		break;
   1076  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_INPKILL:
   1077  1.12.12.2  jdolecek 		/* special case, take away our
   1078  1.12.12.2  jdolecek 		 * increment since WE are the killer
   1079  1.12.12.2  jdolecek 		 */
   1080  1.12.12.2  jdolecek 		SCTP_INP_WLOCK(inp);
   1081  1.12.12.2  jdolecek 		SCTP_INP_DECR_REF(inp);
   1082  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(inp);
   1083  1.12.12.2  jdolecek 		sctp_timer_stop(SCTP_TIMER_TYPE_INPKILL, inp, NULL, NULL);
   1084  1.12.12.2  jdolecek 		sctp_inpcb_free(inp, 1);
   1085  1.12.12.2  jdolecek 		goto out_no_decr;
   1086  1.12.12.2  jdolecek 		break;
   1087  1.12.12.2  jdolecek 	default:
   1088  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   1089  1.12.12.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1090  1.12.12.2  jdolecek 			printf("sctp_timeout_handler:unknown timer %d\n",
   1091  1.12.12.2  jdolecek 			       tmr->type);
   1092  1.12.12.2  jdolecek 		}
   1093  1.12.12.2  jdolecek #endif /* SCTP_DEBUG */
   1094  1.12.12.2  jdolecek 		break;
   1095  1.12.12.2  jdolecek 	};
   1096  1.12.12.2  jdolecek #ifdef SCTP_AUDITING_ENABLED
   1097  1.12.12.2  jdolecek 	sctp_audit_log(0xF1, (u_int8_t)tmr->type);
   1098  1.12.12.2  jdolecek 	sctp_auditing(5, inp, stcb, net);
   1099  1.12.12.2  jdolecek #endif
   1100  1.12.12.2  jdolecek 	if (did_output) {
   1101  1.12.12.2  jdolecek 		/*
   1102  1.12.12.2  jdolecek 		 * Now we need to clean up the control chunk chain if an
   1103  1.12.12.2  jdolecek 		 * ECNE is on it. It must be marked as UNSENT again so next
   1104  1.12.12.2  jdolecek 		 * call will continue to send it until such time that we get
   1105  1.12.12.2  jdolecek 		 * a CWR, to remove it. It is, however, less likely that we
   1106  1.12.12.2  jdolecek 		 * will find a ecn echo on the chain though.
   1107  1.12.12.2  jdolecek 		 */
   1108  1.12.12.2  jdolecek 		sctp_fix_ecn_echo(&stcb->asoc);
   1109  1.12.12.2  jdolecek 	}
   1110  1.12.12.2  jdolecek 	if (stcb) {
   1111  1.12.12.2  jdolecek 		SCTP_TCB_UNLOCK(stcb);
   1112  1.12.12.2  jdolecek 	}
   1113  1.12.12.2  jdolecek  out_decr:
   1114  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(inp);
   1115  1.12.12.2  jdolecek 	SCTP_INP_DECR_REF(inp);
   1116  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(inp);
   1117  1.12.12.2  jdolecek 
   1118  1.12.12.2  jdolecek  out_no_decr:
   1119  1.12.12.2  jdolecek 
   1120  1.12.12.2  jdolecek 	mutex_exit(softnet_lock);
   1121  1.12.12.2  jdolecek }
   1122  1.12.12.2  jdolecek 
   1123  1.12.12.2  jdolecek int
   1124  1.12.12.2  jdolecek sctp_timer_start(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   1125  1.12.12.2  jdolecek     struct sctp_nets *net)
   1126  1.12.12.2  jdolecek {
   1127  1.12.12.2  jdolecek 	int to_ticks;
   1128  1.12.12.2  jdolecek 	struct sctp_timer *tmr;
   1129  1.12.12.2  jdolecek 
   1130  1.12.12.2  jdolecek 	if (inp == NULL)
   1131  1.12.12.2  jdolecek 		return (EFAULT);
   1132  1.12.12.2  jdolecek 
   1133  1.12.12.2  jdolecek 	to_ticks = 0;
   1134  1.12.12.2  jdolecek 
   1135  1.12.12.2  jdolecek 	tmr = NULL;
   1136  1.12.12.2  jdolecek 	switch (t_type) {
   1137  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_ITERATOR:
   1138  1.12.12.2  jdolecek 	{
   1139  1.12.12.2  jdolecek 		struct sctp_iterator *it;
   1140  1.12.12.2  jdolecek 		it = (struct sctp_iterator *)inp;
   1141  1.12.12.2  jdolecek 		tmr = &it->tmr;
   1142  1.12.12.2  jdolecek 		to_ticks = SCTP_ITERATOR_TICKS;
   1143  1.12.12.2  jdolecek 	}
   1144  1.12.12.2  jdolecek 	break;
   1145  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SEND:
   1146  1.12.12.2  jdolecek 		/* Here we use the RTO timer */
   1147  1.12.12.2  jdolecek 	{
   1148  1.12.12.2  jdolecek 		int rto_val;
   1149  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1150  1.12.12.2  jdolecek 			return (EFAULT);
   1151  1.12.12.2  jdolecek 		}
   1152  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1153  1.12.12.2  jdolecek 		if (net->RTO == 0) {
   1154  1.12.12.2  jdolecek 			rto_val = stcb->asoc.initial_rto;
   1155  1.12.12.2  jdolecek 		} else {
   1156  1.12.12.2  jdolecek 			rto_val = net->RTO;
   1157  1.12.12.2  jdolecek 		}
   1158  1.12.12.2  jdolecek 		to_ticks = MSEC_TO_TICKS(rto_val);
   1159  1.12.12.2  jdolecek 	}
   1160  1.12.12.2  jdolecek 	break;
   1161  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_INIT:
   1162  1.12.12.2  jdolecek 		/*
   1163  1.12.12.2  jdolecek 		 * Here we use the INIT timer default
   1164  1.12.12.2  jdolecek 		 * usually about 1 minute.
   1165  1.12.12.2  jdolecek 		 */
   1166  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1167  1.12.12.2  jdolecek 			return (EFAULT);
   1168  1.12.12.2  jdolecek 		}
   1169  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1170  1.12.12.2  jdolecek 		if (net->RTO == 0) {
   1171  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
   1172  1.12.12.2  jdolecek 		} else {
   1173  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(net->RTO);
   1174  1.12.12.2  jdolecek 		}
   1175  1.12.12.2  jdolecek 		break;
   1176  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_RECV:
   1177  1.12.12.2  jdolecek 		/*
   1178  1.12.12.2  jdolecek 		 * Here we use the Delayed-Ack timer value from the inp
   1179  1.12.12.2  jdolecek 		 * ususually about 200ms.
   1180  1.12.12.2  jdolecek 		 */
   1181  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1182  1.12.12.2  jdolecek 			return (EFAULT);
   1183  1.12.12.2  jdolecek 		}
   1184  1.12.12.2  jdolecek 		tmr = &stcb->asoc.dack_timer;
   1185  1.12.12.2  jdolecek 		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV];
   1186  1.12.12.2  jdolecek 		break;
   1187  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWN:
   1188  1.12.12.2  jdolecek 		/* Here we use the RTO of the destination. */
   1189  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1190  1.12.12.2  jdolecek 			return (EFAULT);
   1191  1.12.12.2  jdolecek 		}
   1192  1.12.12.2  jdolecek 
   1193  1.12.12.2  jdolecek 		if (net->RTO == 0) {
   1194  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
   1195  1.12.12.2  jdolecek 		} else {
   1196  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(net->RTO);
   1197  1.12.12.2  jdolecek 		}
   1198  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1199  1.12.12.2  jdolecek 		break;
   1200  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_HEARTBEAT:
   1201  1.12.12.2  jdolecek 		/*
   1202  1.12.12.2  jdolecek 		 * the net is used here so that we can add in the RTO.
   1203  1.12.12.2  jdolecek 		 * Even though we use a different timer. We also add the
   1204  1.12.12.2  jdolecek 		 * HB timer PLUS a random jitter.
   1205  1.12.12.2  jdolecek 		 */
   1206  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1207  1.12.12.2  jdolecek 			return (EFAULT);
   1208  1.12.12.2  jdolecek 		}
   1209  1.12.12.2  jdolecek 		{
   1210  1.12.12.2  jdolecek 			uint32_t rndval;
   1211  1.12.12.2  jdolecek 			uint8_t this_random;
   1212  1.12.12.2  jdolecek 			int cnt_of_unconf=0;
   1213  1.12.12.2  jdolecek 			struct sctp_nets *lnet;
   1214  1.12.12.2  jdolecek 
   1215  1.12.12.2  jdolecek 			TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
   1216  1.12.12.2  jdolecek 				if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
   1217  1.12.12.2  jdolecek 					cnt_of_unconf++;
   1218  1.12.12.2  jdolecek 				}
   1219  1.12.12.2  jdolecek 			}
   1220  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   1221  1.12.12.2  jdolecek 			if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1222  1.12.12.2  jdolecek 				printf("HB timer to start unconfirmed:%d hb_delay:%d\n",
   1223  1.12.12.2  jdolecek 				       cnt_of_unconf, stcb->asoc.heart_beat_delay);
   1224  1.12.12.2  jdolecek 			}
   1225  1.12.12.2  jdolecek #endif
   1226  1.12.12.2  jdolecek 			if (stcb->asoc.hb_random_idx > 3) {
   1227  1.12.12.2  jdolecek 				rndval = sctp_select_initial_TSN(&inp->sctp_ep);
   1228  1.12.12.2  jdolecek 				memcpy(stcb->asoc.hb_random_values, &rndval,
   1229  1.12.12.2  jdolecek 				       sizeof(stcb->asoc.hb_random_values));
   1230  1.12.12.2  jdolecek 				this_random = stcb->asoc.hb_random_values[0];
   1231  1.12.12.2  jdolecek 				stcb->asoc.hb_random_idx = 0;
   1232  1.12.12.2  jdolecek 				stcb->asoc.hb_ect_randombit = 0;
   1233  1.12.12.2  jdolecek 			} else {
   1234  1.12.12.2  jdolecek 				this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
   1235  1.12.12.2  jdolecek 				stcb->asoc.hb_random_idx++;
   1236  1.12.12.2  jdolecek 				stcb->asoc.hb_ect_randombit = 0;
   1237  1.12.12.2  jdolecek 			}
   1238  1.12.12.2  jdolecek 			/*
   1239  1.12.12.2  jdolecek 			 * this_random will be 0 - 256 ms
   1240  1.12.12.2  jdolecek 			 * RTO is in ms.
   1241  1.12.12.2  jdolecek 			 */
   1242  1.12.12.2  jdolecek 			if ((stcb->asoc.heart_beat_delay == 0) &&
   1243  1.12.12.2  jdolecek 			    (cnt_of_unconf == 0)) {
   1244  1.12.12.2  jdolecek 				/* no HB on this inp after confirmations */
   1245  1.12.12.2  jdolecek 				return (0);
   1246  1.12.12.2  jdolecek 			}
   1247  1.12.12.2  jdolecek 			if (net) {
   1248  1.12.12.2  jdolecek 				int delay;
   1249  1.12.12.2  jdolecek 				delay = stcb->asoc.heart_beat_delay;
   1250  1.12.12.2  jdolecek 				TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
   1251  1.12.12.2  jdolecek 					if ((lnet->dest_state & SCTP_ADDR_UNCONFIRMED) &&
   1252  1.12.12.2  jdolecek 					    ((lnet->dest_state & SCTP_ADDR_OUT_OF_SCOPE) == 0) &&
   1253  1.12.12.2  jdolecek 					    (lnet->dest_state & SCTP_ADDR_REACHABLE)) {
   1254  1.12.12.2  jdolecek 					    delay = 0;
   1255  1.12.12.2  jdolecek 					}
   1256  1.12.12.2  jdolecek 				}
   1257  1.12.12.2  jdolecek 				if (net->RTO == 0) {
   1258  1.12.12.2  jdolecek 					/* Never been checked */
   1259  1.12.12.2  jdolecek 					to_ticks = this_random + stcb->asoc.initial_rto + delay;
   1260  1.12.12.2  jdolecek 				} else {
   1261  1.12.12.2  jdolecek 					/* set rto_val to the ms */
   1262  1.12.12.2  jdolecek 					to_ticks = delay + net->RTO + this_random;
   1263  1.12.12.2  jdolecek 				}
   1264  1.12.12.2  jdolecek 			} else {
   1265  1.12.12.2  jdolecek 				if (cnt_of_unconf) {
   1266  1.12.12.2  jdolecek 					to_ticks = this_random + stcb->asoc.initial_rto;
   1267  1.12.12.2  jdolecek 				} else {
   1268  1.12.12.2  jdolecek 					to_ticks = stcb->asoc.heart_beat_delay + this_random + stcb->asoc.initial_rto;
   1269  1.12.12.2  jdolecek 				}
   1270  1.12.12.2  jdolecek 			}
   1271  1.12.12.2  jdolecek 			/*
   1272  1.12.12.2  jdolecek 			 * Now we must convert the to_ticks that are now in
   1273  1.12.12.2  jdolecek 			 * ms to ticks.
   1274  1.12.12.2  jdolecek 			 */
   1275  1.12.12.2  jdolecek 			to_ticks *= hz;
   1276  1.12.12.2  jdolecek 			to_ticks /= 1000;
   1277  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   1278  1.12.12.2  jdolecek 			if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1279  1.12.12.2  jdolecek 				printf("Timer to expire in %d ticks\n", to_ticks);
   1280  1.12.12.2  jdolecek 			}
   1281  1.12.12.2  jdolecek #endif
   1282  1.12.12.2  jdolecek 			tmr = &stcb->asoc.hb_timer;
   1283  1.12.12.2  jdolecek 		}
   1284  1.12.12.2  jdolecek 		break;
   1285  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_COOKIE:
   1286  1.12.12.2  jdolecek 		/*
   1287  1.12.12.2  jdolecek 		 * Here we can use the RTO timer from the network since
   1288  1.12.12.2  jdolecek 		 * one RTT was compelete. If a retran happened then we will
   1289  1.12.12.2  jdolecek 		 * be using the RTO initial value.
   1290  1.12.12.2  jdolecek 		 */
   1291  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1292  1.12.12.2  jdolecek 			return (EFAULT);
   1293  1.12.12.2  jdolecek 		}
   1294  1.12.12.2  jdolecek 		if (net->RTO == 0) {
   1295  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
   1296  1.12.12.2  jdolecek 		} else {
   1297  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(net->RTO);
   1298  1.12.12.2  jdolecek 		}
   1299  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1300  1.12.12.2  jdolecek 		break;
   1301  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_NEWCOOKIE:
   1302  1.12.12.2  jdolecek 		/*
   1303  1.12.12.2  jdolecek 		 * nothing needed but the endpoint here
   1304  1.12.12.2  jdolecek 		 * ususually about 60 minutes.
   1305  1.12.12.2  jdolecek 		 */
   1306  1.12.12.2  jdolecek 		tmr = &inp->sctp_ep.signature_change;
   1307  1.12.12.2  jdolecek 		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_SIGNATURE];
   1308  1.12.12.2  jdolecek 		break;
   1309  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_INPKILL:
   1310  1.12.12.2  jdolecek 		/*
   1311  1.12.12.2  jdolecek 		 * The inp is setup to die. We re-use the
   1312  1.12.12.2  jdolecek 		 * signature_chage timer since that has
   1313  1.12.12.2  jdolecek 		 * stopped and we are in the GONE state.
   1314  1.12.12.2  jdolecek 		 */
   1315  1.12.12.2  jdolecek 		tmr = &inp->sctp_ep.signature_change;
   1316  1.12.12.2  jdolecek 		to_ticks = (SCTP_INP_KILL_TIMEOUT * hz) / 1000;
   1317  1.12.12.2  jdolecek 		break;
   1318  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_PATHMTURAISE:
   1319  1.12.12.2  jdolecek 		/*
   1320  1.12.12.2  jdolecek 		 * Here we use the value found in the EP for PMTU
   1321  1.12.12.2  jdolecek 		 * ususually about 10 minutes.
   1322  1.12.12.2  jdolecek 		 */
   1323  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1324  1.12.12.2  jdolecek 			return (EFAULT);
   1325  1.12.12.2  jdolecek 		}
   1326  1.12.12.2  jdolecek 		if (net == NULL) {
   1327  1.12.12.2  jdolecek 			return (EFAULT);
   1328  1.12.12.2  jdolecek 		}
   1329  1.12.12.2  jdolecek 		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_PMTU];
   1330  1.12.12.2  jdolecek 		tmr = &net->pmtu_timer;
   1331  1.12.12.2  jdolecek 		break;
   1332  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWNACK:
   1333  1.12.12.2  jdolecek 		/* Here we use the RTO of the destination */
   1334  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1335  1.12.12.2  jdolecek 			return (EFAULT);
   1336  1.12.12.2  jdolecek 		}
   1337  1.12.12.2  jdolecek 		if (net->RTO == 0) {
   1338  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
   1339  1.12.12.2  jdolecek 		} else {
   1340  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(net->RTO);
   1341  1.12.12.2  jdolecek 		}
   1342  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1343  1.12.12.2  jdolecek 		break;
   1344  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
   1345  1.12.12.2  jdolecek 		/*
   1346  1.12.12.2  jdolecek 		 * Here we use the endpoints shutdown guard timer
   1347  1.12.12.2  jdolecek 		 * usually about 3 minutes.
   1348  1.12.12.2  jdolecek 		 */
   1349  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1350  1.12.12.2  jdolecek 			return (EFAULT);
   1351  1.12.12.2  jdolecek 		}
   1352  1.12.12.2  jdolecek 		to_ticks = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_MAXSHUTDOWN];
   1353  1.12.12.2  jdolecek 		tmr = &stcb->asoc.shut_guard_timer;
   1354  1.12.12.2  jdolecek 		break;
   1355  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_STRRESET:
   1356  1.12.12.2  jdolecek 		/*
   1357  1.12.12.2  jdolecek 		 * Here the timer comes from the inp
   1358  1.12.12.2  jdolecek 		 * but its value is from the RTO.
   1359  1.12.12.2  jdolecek 		 */
   1360  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1361  1.12.12.2  jdolecek 			return (EFAULT);
   1362  1.12.12.2  jdolecek 		}
   1363  1.12.12.2  jdolecek 		if (net->RTO == 0) {
   1364  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
   1365  1.12.12.2  jdolecek 		} else {
   1366  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(net->RTO);
   1367  1.12.12.2  jdolecek 		}
   1368  1.12.12.2  jdolecek 		tmr = &stcb->asoc.strreset_timer;
   1369  1.12.12.2  jdolecek 		break;
   1370  1.12.12.2  jdolecek 
   1371  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_ASCONF:
   1372  1.12.12.2  jdolecek 		/*
   1373  1.12.12.2  jdolecek 		 * Here the timer comes from the inp
   1374  1.12.12.2  jdolecek 		 * but its value is from the RTO.
   1375  1.12.12.2  jdolecek 		 */
   1376  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1377  1.12.12.2  jdolecek 			return (EFAULT);
   1378  1.12.12.2  jdolecek 		}
   1379  1.12.12.2  jdolecek 		if (net->RTO == 0) {
   1380  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(stcb->asoc.initial_rto);
   1381  1.12.12.2  jdolecek 		} else {
   1382  1.12.12.2  jdolecek 			to_ticks = MSEC_TO_TICKS(net->RTO);
   1383  1.12.12.2  jdolecek 		}
   1384  1.12.12.2  jdolecek 		tmr = &stcb->asoc.asconf_timer;
   1385  1.12.12.2  jdolecek 		break;
   1386  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_AUTOCLOSE:
   1387  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1388  1.12.12.2  jdolecek 			return (EFAULT);
   1389  1.12.12.2  jdolecek 		}
   1390  1.12.12.2  jdolecek 		if (stcb->asoc.sctp_autoclose_ticks == 0) {
   1391  1.12.12.2  jdolecek 			/* Really an error since stcb is NOT set to autoclose */
   1392  1.12.12.2  jdolecek 			return (0);
   1393  1.12.12.2  jdolecek 		}
   1394  1.12.12.2  jdolecek 		to_ticks = stcb->asoc.sctp_autoclose_ticks;
   1395  1.12.12.2  jdolecek 		tmr = &stcb->asoc.autoclose_timer;
   1396  1.12.12.2  jdolecek 		break;
   1397  1.12.12.2  jdolecek 	default:
   1398  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   1399  1.12.12.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1400  1.12.12.2  jdolecek 			printf("sctp_timer_start:Unknown timer type %d\n",
   1401  1.12.12.2  jdolecek 			       t_type);
   1402  1.12.12.2  jdolecek 		}
   1403  1.12.12.2  jdolecek #endif /* SCTP_DEBUG */
   1404  1.12.12.2  jdolecek 		return (EFAULT);
   1405  1.12.12.2  jdolecek 		break;
   1406  1.12.12.2  jdolecek 	};
   1407  1.12.12.2  jdolecek 	if ((to_ticks <= 0) || (tmr == NULL)) {
   1408  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   1409  1.12.12.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1410  1.12.12.2  jdolecek 			printf("sctp_timer_start:%d:software error to_ticks:%d tmr:%p not set ??\n",
   1411  1.12.12.2  jdolecek 			       t_type, to_ticks, tmr);
   1412  1.12.12.2  jdolecek 		}
   1413  1.12.12.2  jdolecek #endif /* SCTP_DEBUG */
   1414  1.12.12.2  jdolecek 		return (EFAULT);
   1415  1.12.12.2  jdolecek 	}
   1416  1.12.12.2  jdolecek 	if (callout_pending(&tmr->timer)) {
   1417  1.12.12.2  jdolecek 		/*
   1418  1.12.12.2  jdolecek 		 * we do NOT allow you to have it already running.
   1419  1.12.12.2  jdolecek 		 * if it is we leave the current one up unchanged
   1420  1.12.12.2  jdolecek 		 */
   1421  1.12.12.2  jdolecek 		return (EALREADY);
   1422  1.12.12.2  jdolecek 	}
   1423  1.12.12.2  jdolecek 	/* At this point we can proceed */
   1424  1.12.12.2  jdolecek 	if (t_type == SCTP_TIMER_TYPE_SEND) {
   1425  1.12.12.2  jdolecek 		stcb->asoc.num_send_timers_up++;
   1426  1.12.12.2  jdolecek 	}
   1427  1.12.12.2  jdolecek 	tmr->type = t_type;
   1428  1.12.12.2  jdolecek 	tmr->ep = (void *)inp;
   1429  1.12.12.2  jdolecek 	tmr->tcb = (void *)stcb;
   1430  1.12.12.2  jdolecek 	tmr->net = (void *)net;
   1431  1.12.12.2  jdolecek 	callout_reset(&tmr->timer, to_ticks, sctp_timeout_handler, tmr);
   1432  1.12.12.2  jdolecek 	return (0);
   1433  1.12.12.2  jdolecek }
   1434  1.12.12.2  jdolecek 
   1435  1.12.12.2  jdolecek int
   1436  1.12.12.2  jdolecek sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   1437  1.12.12.2  jdolecek 		struct sctp_nets *net)
   1438  1.12.12.2  jdolecek {
   1439  1.12.12.2  jdolecek 	struct sctp_timer *tmr;
   1440  1.12.12.2  jdolecek 
   1441  1.12.12.2  jdolecek 	if (inp == NULL)
   1442  1.12.12.2  jdolecek 		return (EFAULT);
   1443  1.12.12.2  jdolecek 
   1444  1.12.12.2  jdolecek 	tmr = NULL;
   1445  1.12.12.2  jdolecek 	switch (t_type) {
   1446  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_ITERATOR:
   1447  1.12.12.2  jdolecek 	{
   1448  1.12.12.2  jdolecek 		struct sctp_iterator *it;
   1449  1.12.12.2  jdolecek 		it = (struct sctp_iterator *)inp;
   1450  1.12.12.2  jdolecek 		tmr = &it->tmr;
   1451  1.12.12.2  jdolecek 	}
   1452  1.12.12.2  jdolecek 	break;
   1453  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SEND:
   1454  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1455  1.12.12.2  jdolecek 			return (EFAULT);
   1456  1.12.12.2  jdolecek 		}
   1457  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1458  1.12.12.2  jdolecek 		break;
   1459  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_INIT:
   1460  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1461  1.12.12.2  jdolecek 			return (EFAULT);
   1462  1.12.12.2  jdolecek 		}
   1463  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1464  1.12.12.2  jdolecek 		break;
   1465  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_RECV:
   1466  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1467  1.12.12.2  jdolecek 			return (EFAULT);
   1468  1.12.12.2  jdolecek 		}
   1469  1.12.12.2  jdolecek 		tmr = &stcb->asoc.dack_timer;
   1470  1.12.12.2  jdolecek 		break;
   1471  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWN:
   1472  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1473  1.12.12.2  jdolecek 			return (EFAULT);
   1474  1.12.12.2  jdolecek 		}
   1475  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1476  1.12.12.2  jdolecek 		break;
   1477  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_HEARTBEAT:
   1478  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1479  1.12.12.2  jdolecek 			return (EFAULT);
   1480  1.12.12.2  jdolecek 		}
   1481  1.12.12.2  jdolecek 		tmr = &stcb->asoc.hb_timer;
   1482  1.12.12.2  jdolecek 		break;
   1483  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_COOKIE:
   1484  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1485  1.12.12.2  jdolecek 			return (EFAULT);
   1486  1.12.12.2  jdolecek 		}
   1487  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1488  1.12.12.2  jdolecek 		break;
   1489  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_NEWCOOKIE:
   1490  1.12.12.2  jdolecek 		/* nothing needed but the endpoint here */
   1491  1.12.12.2  jdolecek 		tmr = &inp->sctp_ep.signature_change;
   1492  1.12.12.2  jdolecek 		/* We re-use the newcookie timer for
   1493  1.12.12.2  jdolecek 		 * the INP kill timer. We must assure
   1494  1.12.12.2  jdolecek 		 * that we do not kill it by accident.
   1495  1.12.12.2  jdolecek 		 */
   1496  1.12.12.2  jdolecek 		break;
   1497  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_INPKILL:
   1498  1.12.12.2  jdolecek 		/*
   1499  1.12.12.2  jdolecek 		 * The inp is setup to die. We re-use the
   1500  1.12.12.2  jdolecek 		 * signature_chage timer since that has
   1501  1.12.12.2  jdolecek 		 * stopped and we are in the GONE state.
   1502  1.12.12.2  jdolecek 		 */
   1503  1.12.12.2  jdolecek 		tmr = &inp->sctp_ep.signature_change;
   1504  1.12.12.2  jdolecek 		break;
   1505  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_PATHMTURAISE:
   1506  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1507  1.12.12.2  jdolecek 			return (EFAULT);
   1508  1.12.12.2  jdolecek 		}
   1509  1.12.12.2  jdolecek 		if (net == NULL) {
   1510  1.12.12.2  jdolecek 			return (EFAULT);
   1511  1.12.12.2  jdolecek 		}
   1512  1.12.12.2  jdolecek 		tmr = &net->pmtu_timer;
   1513  1.12.12.2  jdolecek 		break;
   1514  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWNACK:
   1515  1.12.12.2  jdolecek 		if ((stcb == NULL) || (net == NULL)) {
   1516  1.12.12.2  jdolecek 			return (EFAULT);
   1517  1.12.12.2  jdolecek 		}
   1518  1.12.12.2  jdolecek 		tmr = &net->rxt_timer;
   1519  1.12.12.2  jdolecek 		break;
   1520  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_SHUTDOWNGUARD:
   1521  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1522  1.12.12.2  jdolecek 			return (EFAULT);
   1523  1.12.12.2  jdolecek 		}
   1524  1.12.12.2  jdolecek 		tmr = &stcb->asoc.shut_guard_timer;
   1525  1.12.12.2  jdolecek 		break;
   1526  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_STRRESET:
   1527  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1528  1.12.12.2  jdolecek 			return (EFAULT);
   1529  1.12.12.2  jdolecek 		}
   1530  1.12.12.2  jdolecek 		tmr = &stcb->asoc.strreset_timer;
   1531  1.12.12.2  jdolecek 		break;
   1532  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_ASCONF:
   1533  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1534  1.12.12.2  jdolecek 			return (EFAULT);
   1535  1.12.12.2  jdolecek 		}
   1536  1.12.12.2  jdolecek 		tmr = &stcb->asoc.asconf_timer;
   1537  1.12.12.2  jdolecek 		break;
   1538  1.12.12.2  jdolecek 	case SCTP_TIMER_TYPE_AUTOCLOSE:
   1539  1.12.12.2  jdolecek 		if (stcb == NULL) {
   1540  1.12.12.2  jdolecek 			return (EFAULT);
   1541  1.12.12.2  jdolecek 		}
   1542  1.12.12.2  jdolecek 		tmr = &stcb->asoc.autoclose_timer;
   1543  1.12.12.2  jdolecek 		break;
   1544  1.12.12.2  jdolecek 	default:
   1545  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   1546  1.12.12.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_TIMER1) {
   1547  1.12.12.2  jdolecek 			printf("sctp_timer_stop:Unknown timer type %d\n",
   1548  1.12.12.2  jdolecek 			       t_type);
   1549  1.12.12.2  jdolecek 		}
   1550  1.12.12.2  jdolecek #endif /* SCTP_DEBUG */
   1551  1.12.12.2  jdolecek 		break;
   1552  1.12.12.2  jdolecek 	};
   1553  1.12.12.2  jdolecek 	if (tmr == NULL)
   1554  1.12.12.2  jdolecek 		return (EFAULT);
   1555  1.12.12.2  jdolecek 
   1556  1.12.12.2  jdolecek 	if ((tmr->type != t_type) && tmr->type) {
   1557  1.12.12.2  jdolecek 		/*
   1558  1.12.12.2  jdolecek 		 * Ok we have a timer that is under joint use. Cookie timer
   1559  1.12.12.2  jdolecek 		 * per chance with the SEND timer. We therefore are NOT
   1560  1.12.12.2  jdolecek 		 * running the timer that the caller wants stopped.  So just
   1561  1.12.12.2  jdolecek 		 * return.
   1562  1.12.12.2  jdolecek 		 */
   1563  1.12.12.2  jdolecek 		return (0);
   1564  1.12.12.2  jdolecek 	}
   1565  1.12.12.2  jdolecek 	if (t_type == SCTP_TIMER_TYPE_SEND) {
   1566  1.12.12.2  jdolecek 		stcb->asoc.num_send_timers_up--;
   1567  1.12.12.2  jdolecek 		if (stcb->asoc.num_send_timers_up < 0) {
   1568  1.12.12.2  jdolecek 			stcb->asoc.num_send_timers_up = 0;
   1569  1.12.12.2  jdolecek 		}
   1570  1.12.12.2  jdolecek 	}
   1571  1.12.12.2  jdolecek 	callout_stop(&tmr->timer);
   1572  1.12.12.2  jdolecek 	return (0);
   1573  1.12.12.2  jdolecek }
   1574  1.12.12.2  jdolecek 
   1575  1.12.12.2  jdolecek #ifdef SCTP_USE_ADLER32
   1576  1.12.12.2  jdolecek static uint32_t
   1577  1.12.12.2  jdolecek update_adler32(uint32_t adler, uint8_t *buf, int32_t len)
   1578  1.12.12.2  jdolecek {
   1579  1.12.12.2  jdolecek 	u_int32_t s1 = adler & 0xffff;
   1580  1.12.12.2  jdolecek 	u_int32_t s2 = (adler >> 16) & 0xffff;
   1581  1.12.12.2  jdolecek 	int n;
   1582  1.12.12.2  jdolecek 
   1583  1.12.12.2  jdolecek 	for (n = 0; n < len; n++, buf++) {
   1584  1.12.12.2  jdolecek 		/* s1 = (s1 + buf[n]) % BASE */
   1585  1.12.12.2  jdolecek 		/* first we add */
   1586  1.12.12.2  jdolecek 		s1 = (s1 + *buf);
   1587  1.12.12.2  jdolecek 		/*
   1588  1.12.12.2  jdolecek 		 * now if we need to, we do a mod by subtracting. It seems
   1589  1.12.12.2  jdolecek 		 * a bit faster since I really will only ever do one subtract
   1590  1.12.12.2  jdolecek 		 * at the MOST, since buf[n] is a max of 255.
   1591  1.12.12.2  jdolecek 		 */
   1592  1.12.12.2  jdolecek 		if (s1 >= SCTP_ADLER32_BASE) {
   1593  1.12.12.2  jdolecek 			s1 -= SCTP_ADLER32_BASE;
   1594  1.12.12.2  jdolecek 		}
   1595  1.12.12.2  jdolecek 		/* s2 = (s2 + s1) % BASE */
   1596  1.12.12.2  jdolecek 		/* first we add */
   1597  1.12.12.2  jdolecek 		s2 = (s2 + s1);
   1598  1.12.12.2  jdolecek 		/*
   1599  1.12.12.2  jdolecek 		 * again, it is more efficent (it seems) to subtract since
   1600  1.12.12.2  jdolecek 		 * the most s2 will ever be is (BASE-1 + BASE-1) in the worse
   1601  1.12.12.2  jdolecek 		 * case. This would then be (2 * BASE) - 2, which will still
   1602  1.12.12.2  jdolecek 		 * only do one subtract. On Intel this is much better to do
   1603  1.12.12.2  jdolecek 		 * this way and avoid the divide. Have not -pg'd on sparc.
   1604  1.12.12.2  jdolecek 		 */
   1605  1.12.12.2  jdolecek 		if (s2 >= SCTP_ADLER32_BASE) {
   1606  1.12.12.2  jdolecek 			s2 -= SCTP_ADLER32_BASE;
   1607  1.12.12.2  jdolecek 		}
   1608  1.12.12.2  jdolecek 	}
   1609  1.12.12.2  jdolecek 	/* Return the adler32 of the bytes buf[0..len-1] */
   1610  1.12.12.2  jdolecek 	return ((s2 << 16) + s1);
   1611  1.12.12.2  jdolecek }
   1612  1.12.12.2  jdolecek 
   1613  1.12.12.2  jdolecek #endif
   1614  1.12.12.2  jdolecek 
   1615  1.12.12.2  jdolecek 
   1616  1.12.12.2  jdolecek u_int32_t
   1617  1.12.12.2  jdolecek sctp_calculate_len(struct mbuf *m)
   1618  1.12.12.2  jdolecek {
   1619  1.12.12.2  jdolecek 	u_int32_t tlen=0;
   1620  1.12.12.2  jdolecek 	struct mbuf *at;
   1621  1.12.12.2  jdolecek 	at = m;
   1622  1.12.12.2  jdolecek 	while (at) {
   1623  1.12.12.2  jdolecek 		tlen += at->m_len;
   1624  1.12.12.2  jdolecek 		at = at->m_next;
   1625  1.12.12.2  jdolecek 	}
   1626  1.12.12.2  jdolecek 	return (tlen);
   1627  1.12.12.2  jdolecek }
   1628  1.12.12.2  jdolecek 
   1629  1.12.12.2  jdolecek #if defined(SCTP_WITH_NO_CSUM)
   1630  1.12.12.2  jdolecek 
   1631  1.12.12.2  jdolecek uint32_t
   1632  1.12.12.2  jdolecek sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
   1633  1.12.12.2  jdolecek {
   1634  1.12.12.2  jdolecek 	/*
   1635  1.12.12.2  jdolecek 	 * given a mbuf chain with a packetheader offset by 'offset'
   1636  1.12.12.2  jdolecek 	 * pointing at a sctphdr (with csum set to 0) go through
   1637  1.12.12.2  jdolecek 	 * the chain of m_next's and calculate the SCTP checksum.
   1638  1.12.12.2  jdolecek 	 * This is currently Adler32 but will change to CRC32x
   1639  1.12.12.2  jdolecek 	 * soon. Also has a side bonus calculate the total length
   1640  1.12.12.2  jdolecek 	 * of the mbuf chain.
   1641  1.12.12.2  jdolecek 	 * Note: if offset is greater than the total mbuf length,
   1642  1.12.12.2  jdolecek 	 * checksum=1, pktlen=0 is returned (ie. no real error code)
   1643  1.12.12.2  jdolecek 	 */
   1644  1.12.12.2  jdolecek 	if (pktlen == NULL)
   1645  1.12.12.2  jdolecek 		return (0);
   1646  1.12.12.2  jdolecek 	*pktlen = sctp_calculate_len(m);
   1647  1.12.12.2  jdolecek 	return (0);
   1648  1.12.12.2  jdolecek }
   1649  1.12.12.2  jdolecek 
   1650  1.12.12.2  jdolecek #elif defined(SCTP_USE_INCHKSUM)
   1651  1.12.12.2  jdolecek 
   1652  1.12.12.2  jdolecek #include <machine/in_cksum.h>
   1653  1.12.12.2  jdolecek 
   1654  1.12.12.2  jdolecek uint32_t
   1655  1.12.12.2  jdolecek sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
   1656  1.12.12.2  jdolecek {
   1657  1.12.12.2  jdolecek 	/*
   1658  1.12.12.2  jdolecek 	 * given a mbuf chain with a packetheader offset by 'offset'
   1659  1.12.12.2  jdolecek 	 * pointing at a sctphdr (with csum set to 0) go through
   1660  1.12.12.2  jdolecek 	 * the chain of m_next's and calculate the SCTP checksum.
   1661  1.12.12.2  jdolecek 	 * This is currently Adler32 but will change to CRC32x
   1662  1.12.12.2  jdolecek 	 * soon. Also has a side bonus calculate the total length
   1663  1.12.12.2  jdolecek 	 * of the mbuf chain.
   1664  1.12.12.2  jdolecek 	 * Note: if offset is greater than the total mbuf length,
   1665  1.12.12.2  jdolecek 	 * checksum=1, pktlen=0 is returned (ie. no real error code)
   1666  1.12.12.2  jdolecek 	 */
   1667  1.12.12.2  jdolecek 	int32_t tlen=0;
   1668  1.12.12.2  jdolecek 	struct mbuf *at;
   1669  1.12.12.2  jdolecek 	uint32_t the_sum, retsum;
   1670  1.12.12.2  jdolecek 
   1671  1.12.12.2  jdolecek 	at = m;
   1672  1.12.12.2  jdolecek 	while (at) {
   1673  1.12.12.2  jdolecek 		tlen += at->m_len;
   1674  1.12.12.2  jdolecek 		at = at->m_next;
   1675  1.12.12.2  jdolecek 	}
   1676  1.12.12.2  jdolecek 	the_sum = (uint32_t)(in_cksum_skip(m, tlen, offset));
   1677  1.12.12.2  jdolecek 	if (pktlen != NULL)
   1678  1.12.12.2  jdolecek 		*pktlen = (tlen-offset);
   1679  1.12.12.2  jdolecek 	retsum = htons(the_sum);
   1680  1.12.12.2  jdolecek 	return (the_sum);
   1681  1.12.12.2  jdolecek }
   1682  1.12.12.2  jdolecek 
   1683  1.12.12.2  jdolecek #else
   1684  1.12.12.2  jdolecek 
   1685  1.12.12.2  jdolecek uint32_t
   1686  1.12.12.2  jdolecek sctp_calculate_sum(struct mbuf *m, int32_t *pktlen, uint32_t offset)
   1687  1.12.12.2  jdolecek {
   1688  1.12.12.2  jdolecek 	/*
   1689  1.12.12.2  jdolecek 	 * given a mbuf chain with a packetheader offset by 'offset'
   1690  1.12.12.2  jdolecek 	 * pointing at a sctphdr (with csum set to 0) go through
   1691  1.12.12.2  jdolecek 	 * the chain of m_next's and calculate the SCTP checksum.
   1692  1.12.12.2  jdolecek 	 * This is currently Adler32 but will change to CRC32x
   1693  1.12.12.2  jdolecek 	 * soon. Also has a side bonus calculate the total length
   1694  1.12.12.2  jdolecek 	 * of the mbuf chain.
   1695  1.12.12.2  jdolecek 	 * Note: if offset is greater than the total mbuf length,
   1696  1.12.12.2  jdolecek 	 * checksum=1, pktlen=0 is returned (ie. no real error code)
   1697  1.12.12.2  jdolecek 	 */
   1698  1.12.12.2  jdolecek 	int32_t tlen=0;
   1699  1.12.12.2  jdolecek #ifdef SCTP_USE_ADLER32
   1700  1.12.12.2  jdolecek 	uint32_t base = 1L;
   1701  1.12.12.2  jdolecek #else
   1702  1.12.12.2  jdolecek 	uint32_t base = 0xffffffff;
   1703  1.12.12.2  jdolecek #endif /* SCTP_USE_ADLER32 */
   1704  1.12.12.2  jdolecek 	struct mbuf *at;
   1705  1.12.12.2  jdolecek 	at = m;
   1706  1.12.12.2  jdolecek 	/* find the correct mbuf and offset into mbuf */
   1707  1.12.12.2  jdolecek 	while ((at != NULL) && (offset > (uint32_t)at->m_len)) {
   1708  1.12.12.2  jdolecek 		offset -= at->m_len;	/* update remaining offset left */
   1709  1.12.12.2  jdolecek 		at = at->m_next;
   1710  1.12.12.2  jdolecek 	}
   1711  1.12.12.2  jdolecek 
   1712  1.12.12.2  jdolecek 	while (at != NULL) {
   1713  1.12.12.2  jdolecek #ifdef SCTP_USE_ADLER32
   1714  1.12.12.2  jdolecek 		base = update_adler32(base, at->m_data + offset,
   1715  1.12.12.2  jdolecek 		    at->m_len - offset);
   1716  1.12.12.2  jdolecek #else
   1717  1.12.12.2  jdolecek 		base = update_crc32(base, at->m_data + offset,
   1718  1.12.12.2  jdolecek 		    at->m_len - offset);
   1719  1.12.12.2  jdolecek #endif /* SCTP_USE_ADLER32 */
   1720  1.12.12.2  jdolecek 		tlen += at->m_len - offset;
   1721  1.12.12.2  jdolecek 		/* we only offset once into the first mbuf */
   1722  1.12.12.2  jdolecek 		if (offset) {
   1723  1.12.12.2  jdolecek 			offset = 0;
   1724  1.12.12.2  jdolecek 		}
   1725  1.12.12.2  jdolecek 		at = at->m_next;
   1726  1.12.12.2  jdolecek 	}
   1727  1.12.12.2  jdolecek 	if (pktlen != NULL) {
   1728  1.12.12.2  jdolecek 		*pktlen = tlen;
   1729  1.12.12.2  jdolecek 	}
   1730  1.12.12.2  jdolecek #ifdef SCTP_USE_ADLER32
   1731  1.12.12.2  jdolecek 	/* Adler32 */
   1732  1.12.12.2  jdolecek 	base = htonl(base);
   1733  1.12.12.2  jdolecek #else
   1734  1.12.12.2  jdolecek 	/* CRC-32c */
   1735  1.12.12.2  jdolecek 	base = sctp_csum_finalize(base);
   1736  1.12.12.2  jdolecek #endif
   1737  1.12.12.2  jdolecek 	return (base);
   1738  1.12.12.2  jdolecek }
   1739  1.12.12.2  jdolecek 
   1740  1.12.12.2  jdolecek 
   1741  1.12.12.2  jdolecek #endif
   1742  1.12.12.2  jdolecek 
   1743  1.12.12.2  jdolecek void
   1744  1.12.12.2  jdolecek sctp_mtu_size_reset(struct sctp_inpcb *inp,
   1745  1.12.12.2  jdolecek 		    struct sctp_association *asoc, u_long mtu)
   1746  1.12.12.2  jdolecek {
   1747  1.12.12.2  jdolecek 	/*
   1748  1.12.12.2  jdolecek 	 * Reset the P-MTU size on this association, this involves changing
   1749  1.12.12.2  jdolecek 	 * the asoc MTU, going through ANY chunk+overhead larger than mtu
   1750  1.12.12.2  jdolecek 	 * to allow the DF flag to be cleared.
   1751  1.12.12.2  jdolecek 	 */
   1752  1.12.12.2  jdolecek 	struct sctp_tmit_chunk *chk;
   1753  1.12.12.2  jdolecek 	struct sctp_stream_out *strm;
   1754  1.12.12.2  jdolecek 	unsigned int eff_mtu, ovh;
   1755  1.12.12.2  jdolecek 	asoc->smallest_mtu = mtu;
   1756  1.12.12.2  jdolecek 	if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
   1757  1.12.12.2  jdolecek 		ovh = SCTP_MIN_OVERHEAD;
   1758  1.12.12.2  jdolecek 	} else {
   1759  1.12.12.2  jdolecek 		ovh = SCTP_MIN_V4_OVERHEAD;
   1760  1.12.12.2  jdolecek 	}
   1761  1.12.12.2  jdolecek 	eff_mtu = mtu - ovh;
   1762  1.12.12.2  jdolecek 	/* Now mark any chunks that need to let IP fragment */
   1763  1.12.12.2  jdolecek 	TAILQ_FOREACH(strm, &asoc->out_wheel, next_spoke) {
   1764  1.12.12.2  jdolecek 		TAILQ_FOREACH(chk, &strm->outqueue, sctp_next) {
   1765  1.12.12.2  jdolecek 			if (chk->send_size > eff_mtu) {
   1766  1.12.12.2  jdolecek 				chk->flags &= SCTP_DONT_FRAGMENT;
   1767  1.12.12.2  jdolecek 				chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
   1768  1.12.12.2  jdolecek 			}
   1769  1.12.12.2  jdolecek 		}
   1770  1.12.12.2  jdolecek 	}
   1771  1.12.12.2  jdolecek 	TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
   1772  1.12.12.2  jdolecek 		if (chk->send_size > eff_mtu) {
   1773  1.12.12.2  jdolecek 			chk->flags &= SCTP_DONT_FRAGMENT;
   1774  1.12.12.2  jdolecek 			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
   1775  1.12.12.2  jdolecek 		}
   1776  1.12.12.2  jdolecek 	}
   1777  1.12.12.2  jdolecek 	TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
   1778  1.12.12.2  jdolecek 		if (chk->send_size > eff_mtu) {
   1779  1.12.12.2  jdolecek 			chk->flags &= SCTP_DONT_FRAGMENT;
   1780  1.12.12.2  jdolecek 			chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
   1781  1.12.12.2  jdolecek 		}
   1782  1.12.12.2  jdolecek 	}
   1783  1.12.12.2  jdolecek }
   1784  1.12.12.2  jdolecek 
   1785  1.12.12.2  jdolecek 
   1786  1.12.12.2  jdolecek /*
   1787  1.12.12.2  jdolecek  * given an association and starting time of the current RTT period
   1788  1.12.12.2  jdolecek  * return RTO in number of usecs
   1789  1.12.12.2  jdolecek  * net should point to the current network
   1790  1.12.12.2  jdolecek  */
   1791  1.12.12.2  jdolecek u_int32_t
   1792  1.12.12.2  jdolecek sctp_calculate_rto(struct sctp_tcb *stcb,
   1793  1.12.12.2  jdolecek 		   struct sctp_association *asoc,
   1794  1.12.12.2  jdolecek 		   struct sctp_nets *net,
   1795  1.12.12.2  jdolecek 		   struct timeval *old)
   1796  1.12.12.2  jdolecek {
   1797  1.12.12.2  jdolecek 	/*
   1798  1.12.12.2  jdolecek 	 * given an association and the starting time of the current RTT
   1799  1.12.12.2  jdolecek 	 * period (in value1/value2) return RTO in number of usecs.
   1800  1.12.12.2  jdolecek 	 */
   1801  1.12.12.2  jdolecek 	int calc_time = 0;
   1802  1.12.12.2  jdolecek 	unsigned int new_rto = 0;
   1803  1.12.12.2  jdolecek 	int first_measure = 0;
   1804  1.12.12.2  jdolecek 	struct timeval now;
   1805  1.12.12.2  jdolecek 
   1806  1.12.12.2  jdolecek 	/************************/
   1807  1.12.12.2  jdolecek 	/* 1. calculate new RTT */
   1808  1.12.12.2  jdolecek 	/************************/
   1809  1.12.12.2  jdolecek 	/* get the current time */
   1810  1.12.12.2  jdolecek 	SCTP_GETTIME_TIMEVAL(&now);
   1811  1.12.12.2  jdolecek 	/* compute the RTT value */
   1812  1.12.12.2  jdolecek 	if ((u_long)now.tv_sec > (u_long)old->tv_sec) {
   1813  1.12.12.2  jdolecek 		calc_time = ((u_long)now.tv_sec - (u_long)old->tv_sec) * 1000;
   1814  1.12.12.2  jdolecek 		if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
   1815  1.12.12.2  jdolecek 			calc_time += (((u_long)now.tv_usec -
   1816  1.12.12.2  jdolecek 				       (u_long)old->tv_usec)/1000);
   1817  1.12.12.2  jdolecek 		} else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
   1818  1.12.12.2  jdolecek 			/* Borrow 1,000ms from current calculation */
   1819  1.12.12.2  jdolecek 			calc_time -= 1000;
   1820  1.12.12.2  jdolecek 			/* Add in the slop over */
   1821  1.12.12.2  jdolecek 			calc_time += ((int)now.tv_usec/1000);
   1822  1.12.12.2  jdolecek 			/* Add in the pre-second ms's */
   1823  1.12.12.2  jdolecek 			calc_time += (((int)1000000 - (int)old->tv_usec)/1000);
   1824  1.12.12.2  jdolecek 		}
   1825  1.12.12.2  jdolecek 	} else if ((u_long)now.tv_sec == (u_long)old->tv_sec) {
   1826  1.12.12.2  jdolecek 		if ((u_long)now.tv_usec > (u_long)old->tv_usec) {
   1827  1.12.12.2  jdolecek 			calc_time = ((u_long)now.tv_usec -
   1828  1.12.12.2  jdolecek 				     (u_long)old->tv_usec)/1000;
   1829  1.12.12.2  jdolecek 		} else if ((u_long)now.tv_usec < (u_long)old->tv_usec) {
   1830  1.12.12.2  jdolecek 			/* impossible .. garbage in nothing out */
   1831  1.12.12.2  jdolecek 			return (((net->lastsa >> 2) + net->lastsv) >> 1);
   1832  1.12.12.2  jdolecek 		} else {
   1833  1.12.12.2  jdolecek 			/* impossible .. garbage in nothing out */
   1834  1.12.12.2  jdolecek 			return (((net->lastsa >> 2) + net->lastsv) >> 1);
   1835  1.12.12.2  jdolecek 		}
   1836  1.12.12.2  jdolecek 	} else {
   1837  1.12.12.2  jdolecek 		/* Clock wrapped? */
   1838  1.12.12.2  jdolecek 		return (((net->lastsa >> 2) + net->lastsv) >> 1);
   1839  1.12.12.2  jdolecek 	}
   1840  1.12.12.2  jdolecek 	/***************************/
   1841  1.12.12.2  jdolecek 	/* 2. update RTTVAR & SRTT */
   1842  1.12.12.2  jdolecek 	/***************************/
   1843  1.12.12.2  jdolecek #if 0
   1844  1.12.12.2  jdolecek 	/*	if (net->lastsv || net->lastsa) {*/
   1845  1.12.12.2  jdolecek 	/* per Section 5.3.1 C3 in SCTP */
   1846  1.12.12.2  jdolecek 	/*		net->lastsv = (int) 	*//* RTTVAR */
   1847  1.12.12.2  jdolecek 	/*			(((double)(1.0 - 0.25) * (double)net->lastsv) +
   1848  1.12.12.2  jdolecek 				(double)(0.25 * (double)abs(net->lastsa - calc_time)));
   1849  1.12.12.2  jdolecek 				net->lastsa = (int) */	/* SRTT */
   1850  1.12.12.2  jdolecek 	/*(((double)(1.0 - 0.125) * (double)net->lastsa) +
   1851  1.12.12.2  jdolecek 	  (double)(0.125 * (double)calc_time));
   1852  1.12.12.2  jdolecek 	  } else {
   1853  1.12.12.2  jdolecek 	*//* the first RTT calculation, per C2 Section 5.3.1 */
   1854  1.12.12.2  jdolecek 	/*		net->lastsa = calc_time;	*//* SRTT */
   1855  1.12.12.2  jdolecek 	/*		net->lastsv = calc_time / 2;	*//* RTTVAR */
   1856  1.12.12.2  jdolecek 	/*	}*/
   1857  1.12.12.2  jdolecek 	/* if RTTVAR goes to 0 you set to clock grainularity */
   1858  1.12.12.2  jdolecek 	/*	if (net->lastsv == 0) {
   1859  1.12.12.2  jdolecek 		net->lastsv = SCTP_CLOCK_GRANULARITY;
   1860  1.12.12.2  jdolecek 		}
   1861  1.12.12.2  jdolecek 		new_rto = net->lastsa + 4 * net->lastsv;
   1862  1.12.12.2  jdolecek 	*/
   1863  1.12.12.2  jdolecek #endif
   1864  1.12.12.2  jdolecek 	/* this is Van Jacobson's integer version */
   1865  1.12.12.2  jdolecek 	if (net->RTO) {
   1866  1.12.12.2  jdolecek 		calc_time -= (net->lastsa >> 3);
   1867  1.12.12.2  jdolecek 		net->lastsa += calc_time;
   1868  1.12.12.2  jdolecek 		if (calc_time < 0) {
   1869  1.12.12.2  jdolecek 			calc_time = -calc_time;
   1870  1.12.12.2  jdolecek 		}
   1871  1.12.12.2  jdolecek 		calc_time -= (net->lastsv >> 2);
   1872  1.12.12.2  jdolecek 		net->lastsv += calc_time;
   1873  1.12.12.2  jdolecek 		if (net->lastsv == 0) {
   1874  1.12.12.2  jdolecek 			net->lastsv = SCTP_CLOCK_GRANULARITY;
   1875  1.12.12.2  jdolecek 		}
   1876  1.12.12.2  jdolecek 	} else {
   1877  1.12.12.2  jdolecek 		/* First RTO measurment */
   1878  1.12.12.2  jdolecek 		net->lastsa = calc_time;
   1879  1.12.12.2  jdolecek 		net->lastsv = calc_time >> 1;
   1880  1.12.12.2  jdolecek 		first_measure = 1;
   1881  1.12.12.2  jdolecek 	}
   1882  1.12.12.2  jdolecek 	new_rto = ((net->lastsa >> 2) + net->lastsv) >> 1;
   1883  1.12.12.2  jdolecek 	if ((new_rto > SCTP_SAT_NETWORK_MIN) &&
   1884  1.12.12.2  jdolecek 	    (stcb->asoc.sat_network_lockout == 0)) {
   1885  1.12.12.2  jdolecek 		stcb->asoc.sat_network = 1;
   1886  1.12.12.2  jdolecek 	} else 	if ((!first_measure) && stcb->asoc.sat_network) {
   1887  1.12.12.2  jdolecek 		stcb->asoc.sat_network = 0;
   1888  1.12.12.2  jdolecek 		stcb->asoc.sat_network_lockout = 1;
   1889  1.12.12.2  jdolecek 	}
   1890  1.12.12.2  jdolecek 	/* bound it, per C6/C7 in Section 5.3.1 */
   1891  1.12.12.2  jdolecek 	if (new_rto < stcb->asoc.minrto) {
   1892  1.12.12.2  jdolecek 		new_rto = stcb->asoc.minrto;
   1893  1.12.12.2  jdolecek 	}
   1894  1.12.12.2  jdolecek 	if (new_rto > stcb->asoc.maxrto) {
   1895  1.12.12.2  jdolecek 		new_rto = stcb->asoc.maxrto;
   1896  1.12.12.2  jdolecek 	}
   1897  1.12.12.2  jdolecek 	/* we are now returning the RTT Smoothed */
   1898  1.12.12.2  jdolecek 	return ((u_int32_t)new_rto);
   1899  1.12.12.2  jdolecek }
   1900  1.12.12.2  jdolecek 
   1901  1.12.12.2  jdolecek 
   1902  1.12.12.2  jdolecek /*
   1903  1.12.12.2  jdolecek  * return a pointer to a contiguous piece of data from the given
   1904  1.12.12.2  jdolecek  * mbuf chain starting at 'off' for 'len' bytes.  If the desired
   1905  1.12.12.2  jdolecek  * piece spans more than one mbuf, a copy is made at 'ptr'.
   1906  1.12.12.2  jdolecek  * caller must ensure that the buffer size is >= 'len'
   1907  1.12.12.2  jdolecek  * returns NULL if there there isn't 'len' bytes in the chain.
   1908  1.12.12.2  jdolecek  */
   1909  1.12.12.2  jdolecek void *
   1910  1.12.12.2  jdolecek sctp_m_getptr(struct mbuf *m, int off, int len, u_int8_t *in_ptr)
   1911  1.12.12.2  jdolecek {
   1912  1.12.12.2  jdolecek 	uint32_t count;
   1913  1.12.12.2  jdolecek 	uint8_t *ptr;
   1914  1.12.12.2  jdolecek 	ptr = in_ptr;
   1915  1.12.12.2  jdolecek 	if ((off < 0) || (len <= 0))
   1916  1.12.12.2  jdolecek 		return (NULL);
   1917  1.12.12.2  jdolecek 
   1918  1.12.12.2  jdolecek 	/* find the desired start location */
   1919  1.12.12.2  jdolecek 	while ((m != NULL) && (off > 0)) {
   1920  1.12.12.2  jdolecek 		if (off < m->m_len)
   1921  1.12.12.2  jdolecek 			break;
   1922  1.12.12.2  jdolecek 		off -= m->m_len;
   1923  1.12.12.2  jdolecek 		m = m->m_next;
   1924  1.12.12.2  jdolecek 	}
   1925  1.12.12.2  jdolecek 	if (m == NULL)
   1926  1.12.12.2  jdolecek 		return (NULL);
   1927  1.12.12.2  jdolecek 
   1928  1.12.12.2  jdolecek 	/* is the current mbuf large enough (eg. contiguous)? */
   1929  1.12.12.2  jdolecek 	if ((m->m_len - off) >= len) {
   1930  1.12.12.2  jdolecek 		return ((void *)(mtod(m, vaddr_t) + off));
   1931  1.12.12.2  jdolecek 	} else {
   1932  1.12.12.2  jdolecek 		/* else, it spans more than one mbuf, so save a temp copy... */
   1933  1.12.12.2  jdolecek 		while ((m != NULL) && (len > 0)) {
   1934  1.12.12.2  jdolecek 			count = min(m->m_len - off, len);
   1935  1.12.12.2  jdolecek 			memcpy(ptr, (void *)(mtod(m, vaddr_t) + off), count);
   1936  1.12.12.2  jdolecek 			len -= count;
   1937  1.12.12.2  jdolecek 			ptr += count;
   1938  1.12.12.2  jdolecek 			off = 0;
   1939  1.12.12.2  jdolecek 			m = m->m_next;
   1940  1.12.12.2  jdolecek 		}
   1941  1.12.12.2  jdolecek 		if ((m == NULL) && (len > 0))
   1942  1.12.12.2  jdolecek 			return (NULL);
   1943  1.12.12.2  jdolecek 		else
   1944  1.12.12.2  jdolecek 			return ((void *)in_ptr);
   1945  1.12.12.2  jdolecek 	}
   1946  1.12.12.2  jdolecek }
   1947  1.12.12.2  jdolecek 
   1948  1.12.12.2  jdolecek 
   1949  1.12.12.2  jdolecek struct sctp_paramhdr *
   1950  1.12.12.2  jdolecek sctp_get_next_param(struct mbuf *m,
   1951  1.12.12.2  jdolecek 		    int offset,
   1952  1.12.12.2  jdolecek 		    struct sctp_paramhdr *pull,
   1953  1.12.12.2  jdolecek 		    int pull_limit)
   1954  1.12.12.2  jdolecek {
   1955  1.12.12.2  jdolecek 	/* This just provides a typed signature to Peter's Pull routine */
   1956  1.12.12.2  jdolecek 	return ((struct sctp_paramhdr *)sctp_m_getptr(m, offset, pull_limit,
   1957  1.12.12.2  jdolecek     	    (u_int8_t *)pull));
   1958  1.12.12.2  jdolecek }
   1959  1.12.12.2  jdolecek 
   1960  1.12.12.2  jdolecek 
   1961  1.12.12.2  jdolecek int
   1962  1.12.12.2  jdolecek sctp_add_pad_tombuf(struct mbuf *m, int padlen)
   1963  1.12.12.2  jdolecek {
   1964  1.12.12.2  jdolecek 	/*
   1965  1.12.12.2  jdolecek 	 * add padlen bytes of 0 filled padding to the end of the mbuf.
   1966  1.12.12.2  jdolecek 	 * If padlen is > 3 this routine will fail.
   1967  1.12.12.2  jdolecek 	 */
   1968  1.12.12.2  jdolecek 	u_int8_t *dp;
   1969  1.12.12.2  jdolecek 	int i;
   1970  1.12.12.2  jdolecek 	if (padlen > 3) {
   1971  1.12.12.2  jdolecek 		return (ENOBUFS);
   1972  1.12.12.2  jdolecek 	}
   1973  1.12.12.2  jdolecek 	if (M_TRAILINGSPACE(m)) {
   1974  1.12.12.2  jdolecek 		/*
   1975  1.12.12.2  jdolecek 		 * The easy way.
   1976  1.12.12.2  jdolecek 		 * We hope the majority of the time we hit here :)
   1977  1.12.12.2  jdolecek 		 */
   1978  1.12.12.2  jdolecek 		dp = (u_int8_t *)(mtod(m, vaddr_t) + m->m_len);
   1979  1.12.12.2  jdolecek 		m->m_len += padlen;
   1980  1.12.12.2  jdolecek 	} else {
   1981  1.12.12.2  jdolecek 		/* Hard way we must grow the mbuf */
   1982  1.12.12.2  jdolecek 		struct mbuf *tmp;
   1983  1.12.12.2  jdolecek 		MGET(tmp, M_DONTWAIT, MT_DATA);
   1984  1.12.12.2  jdolecek 		if (tmp == NULL) {
   1985  1.12.12.2  jdolecek 			/* Out of space GAK! we are in big trouble. */
   1986  1.12.12.2  jdolecek 			return (ENOSPC);
   1987  1.12.12.2  jdolecek 		}
   1988  1.12.12.2  jdolecek 		/* setup and insert in middle */
   1989  1.12.12.2  jdolecek 		tmp->m_next = m->m_next;
   1990  1.12.12.2  jdolecek 		tmp->m_len = padlen;
   1991  1.12.12.2  jdolecek 		m->m_next = tmp;
   1992  1.12.12.2  jdolecek 		dp = mtod(tmp, u_int8_t *);
   1993  1.12.12.2  jdolecek 	}
   1994  1.12.12.2  jdolecek 	/* zero out the pad */
   1995  1.12.12.2  jdolecek 	for (i=  0; i < padlen; i++) {
   1996  1.12.12.2  jdolecek 		*dp = 0;
   1997  1.12.12.2  jdolecek 		dp++;
   1998  1.12.12.2  jdolecek 	}
   1999  1.12.12.2  jdolecek 	return (0);
   2000  1.12.12.2  jdolecek }
   2001  1.12.12.2  jdolecek 
   2002  1.12.12.2  jdolecek int
   2003  1.12.12.2  jdolecek sctp_pad_lastmbuf(struct mbuf *m, int padval)
   2004  1.12.12.2  jdolecek {
   2005  1.12.12.2  jdolecek 	/* find the last mbuf in chain and pad it */
   2006  1.12.12.2  jdolecek 	struct mbuf *m_at;
   2007  1.12.12.2  jdolecek 	m_at = m;
   2008  1.12.12.2  jdolecek 	while (m_at) {
   2009  1.12.12.2  jdolecek 		if (m_at->m_next == NULL) {
   2010  1.12.12.2  jdolecek 			return (sctp_add_pad_tombuf(m_at, padval));
   2011  1.12.12.2  jdolecek 		}
   2012  1.12.12.2  jdolecek 		m_at = m_at->m_next;
   2013  1.12.12.2  jdolecek 	}
   2014  1.12.12.2  jdolecek 	return (EFAULT);
   2015  1.12.12.2  jdolecek }
   2016  1.12.12.2  jdolecek 
   2017  1.12.12.2  jdolecek static void
   2018  1.12.12.2  jdolecek sctp_notify_assoc_change(u_int32_t event, struct sctp_tcb *stcb,
   2019  1.12.12.2  jdolecek     u_int32_t error)
   2020  1.12.12.2  jdolecek {
   2021  1.12.12.2  jdolecek 	struct mbuf *m_notify;
   2022  1.12.12.2  jdolecek 	struct sctp_assoc_change *sac;
   2023  1.12.12.2  jdolecek 	const struct sockaddr *to;
   2024  1.12.12.2  jdolecek 	struct sockaddr_in6 sin6, lsa6;
   2025  1.12.12.2  jdolecek 
   2026  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   2027  1.12.12.2  jdolecek 	printf("notify: %d\n", event);
   2028  1.12.12.2  jdolecek #endif
   2029  1.12.12.2  jdolecek 	/*
   2030  1.12.12.2  jdolecek 	 * First if we are are going down dump everything we
   2031  1.12.12.2  jdolecek 	 * can to the socket rcv queue.
   2032  1.12.12.2  jdolecek 	 */
   2033  1.12.12.2  jdolecek 	if ((event == SCTP_SHUTDOWN_COMP) || (event == SCTP_COMM_LOST)) {
   2034  1.12.12.2  jdolecek 		sctp_deliver_data(stcb, &stcb->asoc, NULL, 0);
   2035  1.12.12.2  jdolecek 	}
   2036  1.12.12.2  jdolecek 
   2037  1.12.12.2  jdolecek 	/*
   2038  1.12.12.2  jdolecek 	 * For TCP model AND UDP connected sockets we will send
   2039  1.12.12.2  jdolecek 	 * an error up when an ABORT comes in.
   2040  1.12.12.2  jdolecek 	 */
   2041  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2042  1.12.12.2  jdolecek 	     (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) &&
   2043  1.12.12.2  jdolecek 	    (event == SCTP_COMM_LOST)) {
   2044  1.12.12.2  jdolecek 		stcb->sctp_socket->so_error = ECONNRESET;
   2045  1.12.12.2  jdolecek 		/* Wake ANY sleepers */
   2046  1.12.12.2  jdolecek 		sowwakeup(stcb->sctp_socket);
   2047  1.12.12.2  jdolecek 		sorwakeup(stcb->sctp_socket);
   2048  1.12.12.2  jdolecek 	}
   2049  1.12.12.2  jdolecek #if 0
   2050  1.12.12.2  jdolecek 	if ((event == SCTP_COMM_UP) &&
   2051  1.12.12.2  jdolecek 	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
   2052  1.12.12.2  jdolecek  	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
   2053  1.12.12.2  jdolecek 		 soisconnected(stcb->sctp_socket);
   2054  1.12.12.2  jdolecek 	}
   2055  1.12.12.2  jdolecek #endif
   2056  1.12.12.2  jdolecek 	if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVASSOCEVNT)) {
   2057  1.12.12.2  jdolecek 		/* event not enabled */
   2058  1.12.12.2  jdolecek 		return;
   2059  1.12.12.2  jdolecek 	}
   2060  1.12.12.2  jdolecek 	MGETHDR(m_notify, M_DONTWAIT, MT_DATA);
   2061  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2062  1.12.12.2  jdolecek 		/* no space left */
   2063  1.12.12.2  jdolecek 		return;
   2064  1.12.12.2  jdolecek 	m_notify->m_len = 0;
   2065  1.12.12.2  jdolecek 
   2066  1.12.12.2  jdolecek 	sac = mtod(m_notify, struct sctp_assoc_change *);
   2067  1.12.12.2  jdolecek 	sac->sac_type = SCTP_ASSOC_CHANGE;
   2068  1.12.12.2  jdolecek 	sac->sac_flags = 0;
   2069  1.12.12.2  jdolecek 	sac->sac_length = sizeof(struct sctp_assoc_change);
   2070  1.12.12.2  jdolecek 	sac->sac_state = event;
   2071  1.12.12.2  jdolecek 	sac->sac_error = error;
   2072  1.12.12.2  jdolecek 	/* XXX verify these stream counts */
   2073  1.12.12.2  jdolecek 	sac->sac_outbound_streams = stcb->asoc.streamoutcnt;
   2074  1.12.12.2  jdolecek 	sac->sac_inbound_streams = stcb->asoc.streamincnt;
   2075  1.12.12.2  jdolecek 	sac->sac_assoc_id = sctp_get_associd(stcb);
   2076  1.12.12.2  jdolecek 
   2077  1.12.12.2  jdolecek 	m_notify->m_flags |= M_EOR | M_NOTIFICATION;
   2078  1.12.12.2  jdolecek 	m_notify->m_pkthdr.len = sizeof(struct sctp_assoc_change);
   2079  1.12.12.2  jdolecek 	m_reset_rcvif(m_notify);
   2080  1.12.12.2  jdolecek 	m_notify->m_len = sizeof(struct sctp_assoc_change);
   2081  1.12.12.2  jdolecek 	m_notify->m_next = NULL;
   2082  1.12.12.2  jdolecek 
   2083  1.12.12.2  jdolecek 	/* append to socket */
   2084  1.12.12.2  jdolecek 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
   2085  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
   2086  1.12.12.2  jdolecek 	    to->sa_family == AF_INET) {
   2087  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   2088  1.12.12.2  jdolecek 
   2089  1.12.12.2  jdolecek 		sin = (const struct sockaddr_in *)to;
   2090  1.12.12.2  jdolecek 		in6_sin_2_v4mapsin6(sin, &sin6);
   2091  1.12.12.2  jdolecek 		to = (struct sockaddr *)&sin6;
   2092  1.12.12.2  jdolecek 	}
   2093  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2094  1.12.12.2  jdolecek 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
   2095  1.12.12.2  jdolecek 						   &lsa6);
   2096  1.12.12.2  jdolecek 	/*
   2097  1.12.12.2  jdolecek 	 * We need to always notify comm changes.
   2098  1.12.12.2  jdolecek 	 * if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
   2099  1.12.12.2  jdolecek 	 * 	sctp_m_freem(m_notify);
   2100  1.12.12.2  jdolecek 	 *	return;
   2101  1.12.12.2  jdolecek 	 * }
   2102  1.12.12.2  jdolecek 	*/
   2103  1.12.12.2  jdolecek 	SCTP_TCB_UNLOCK(stcb);
   2104  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(stcb->sctp_ep);
   2105  1.12.12.2  jdolecek 	SCTP_TCB_LOCK(stcb);
   2106  1.12.12.2  jdolecek 	if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv,
   2107  1.12.12.2  jdolecek 	    to, m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
   2108  1.12.12.2  jdolecek 		/* not enough room */
   2109  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2110  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2111  1.12.12.2  jdolecek 		return;
   2112  1.12.12.2  jdolecek 	}
   2113  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   2114  1.12.12.2  jdolecek 	   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
   2115  1.12.12.2  jdolecek 		if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
   2116  1.12.12.2  jdolecek 			stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2117  1.12.12.2  jdolecek 		}
   2118  1.12.12.2  jdolecek 	} else {
   2119  1.12.12.2  jdolecek 		stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2120  1.12.12.2  jdolecek 	}
   2121  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2122  1.12.12.2  jdolecek 	/* Wake up any sleeper */
   2123  1.12.12.2  jdolecek 	sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2124  1.12.12.2  jdolecek 	sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2125  1.12.12.2  jdolecek }
   2126  1.12.12.2  jdolecek 
   2127  1.12.12.2  jdolecek static void
   2128  1.12.12.2  jdolecek sctp_notify_peer_addr_change(struct sctp_tcb *stcb, uint32_t state,
   2129  1.12.12.2  jdolecek     const struct sockaddr *sa, uint32_t error)
   2130  1.12.12.2  jdolecek {
   2131  1.12.12.2  jdolecek 	struct mbuf *m_notify;
   2132  1.12.12.2  jdolecek 	struct sctp_paddr_change *spc;
   2133  1.12.12.2  jdolecek 	const struct sockaddr *to;
   2134  1.12.12.2  jdolecek 	struct sockaddr_in6 sin6, lsa6;
   2135  1.12.12.2  jdolecek 
   2136  1.12.12.2  jdolecek 	if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVPADDREVNT))
   2137  1.12.12.2  jdolecek 		/* event not enabled */
   2138  1.12.12.2  jdolecek 		return;
   2139  1.12.12.2  jdolecek 
   2140  1.12.12.2  jdolecek 	MGETHDR(m_notify, M_DONTWAIT, MT_DATA);
   2141  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2142  1.12.12.2  jdolecek 		return;
   2143  1.12.12.2  jdolecek 	m_notify->m_len = 0;
   2144  1.12.12.2  jdolecek 
   2145  1.12.12.2  jdolecek 	MCLGET(m_notify, M_DONTWAIT);
   2146  1.12.12.2  jdolecek 	if ((m_notify->m_flags & M_EXT) != M_EXT) {
   2147  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2148  1.12.12.2  jdolecek 		return;
   2149  1.12.12.2  jdolecek 	}
   2150  1.12.12.2  jdolecek 
   2151  1.12.12.2  jdolecek 	spc = mtod(m_notify, struct sctp_paddr_change *);
   2152  1.12.12.2  jdolecek 	spc->spc_type = SCTP_PEER_ADDR_CHANGE;
   2153  1.12.12.2  jdolecek 	spc->spc_flags = 0;
   2154  1.12.12.2  jdolecek 	spc->spc_length = sizeof(struct sctp_paddr_change);
   2155  1.12.12.2  jdolecek 	if (sa->sa_family == AF_INET) {
   2156  1.12.12.2  jdolecek 		memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
   2157  1.12.12.2  jdolecek 	} else {
   2158  1.12.12.2  jdolecek 		memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
   2159  1.12.12.2  jdolecek 	}
   2160  1.12.12.2  jdolecek 	spc->spc_state = state;
   2161  1.12.12.2  jdolecek 	spc->spc_error = error;
   2162  1.12.12.2  jdolecek 	spc->spc_assoc_id = sctp_get_associd(stcb);
   2163  1.12.12.2  jdolecek 
   2164  1.12.12.2  jdolecek 	m_notify->m_flags |= M_EOR | M_NOTIFICATION;
   2165  1.12.12.2  jdolecek 	m_notify->m_pkthdr.len = sizeof(struct sctp_paddr_change);
   2166  1.12.12.2  jdolecek 	m_reset_rcvif(m_notify);
   2167  1.12.12.2  jdolecek 	m_notify->m_len = sizeof(struct sctp_paddr_change);
   2168  1.12.12.2  jdolecek 	m_notify->m_next = NULL;
   2169  1.12.12.2  jdolecek 
   2170  1.12.12.2  jdolecek 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
   2171  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
   2172  1.12.12.2  jdolecek 	    to->sa_family == AF_INET) {
   2173  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   2174  1.12.12.2  jdolecek 
   2175  1.12.12.2  jdolecek 		sin = (const struct sockaddr_in *)to;
   2176  1.12.12.2  jdolecek 		in6_sin_2_v4mapsin6(sin, &sin6);
   2177  1.12.12.2  jdolecek 		to = (struct sockaddr *)&sin6;
   2178  1.12.12.2  jdolecek 	}
   2179  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2180  1.12.12.2  jdolecek 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
   2181  1.12.12.2  jdolecek 	    &lsa6);
   2182  1.12.12.2  jdolecek 
   2183  1.12.12.2  jdolecek 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
   2184  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2185  1.12.12.2  jdolecek 		return;
   2186  1.12.12.2  jdolecek 	}
   2187  1.12.12.2  jdolecek 	/* append to socket */
   2188  1.12.12.2  jdolecek 	SCTP_TCB_UNLOCK(stcb);
   2189  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(stcb->sctp_ep);
   2190  1.12.12.2  jdolecek 	SCTP_TCB_LOCK(stcb);
   2191  1.12.12.2  jdolecek 	if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
   2192  1.12.12.2  jdolecek 	    m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
   2193  1.12.12.2  jdolecek 		/* not enough room */
   2194  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2195  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2196  1.12.12.2  jdolecek 		return;
   2197  1.12.12.2  jdolecek 	}
   2198  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   2199  1.12.12.2  jdolecek 	   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
   2200  1.12.12.2  jdolecek 		if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
   2201  1.12.12.2  jdolecek 			stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2202  1.12.12.2  jdolecek 		}
   2203  1.12.12.2  jdolecek 	} else {
   2204  1.12.12.2  jdolecek 		stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2205  1.12.12.2  jdolecek 	}
   2206  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2207  1.12.12.2  jdolecek 	sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2208  1.12.12.2  jdolecek }
   2209  1.12.12.2  jdolecek 
   2210  1.12.12.2  jdolecek 
   2211  1.12.12.2  jdolecek static void
   2212  1.12.12.2  jdolecek sctp_notify_send_failed(struct sctp_tcb *stcb, u_int32_t error,
   2213  1.12.12.2  jdolecek 			struct sctp_tmit_chunk *chk)
   2214  1.12.12.2  jdolecek {
   2215  1.12.12.2  jdolecek 	struct mbuf *m_notify;
   2216  1.12.12.2  jdolecek 	struct sctp_send_failed *ssf;
   2217  1.12.12.2  jdolecek 	struct sockaddr_in6 sin6, lsa6;
   2218  1.12.12.2  jdolecek 	const struct sockaddr *to;
   2219  1.12.12.2  jdolecek 	int length;
   2220  1.12.12.2  jdolecek 
   2221  1.12.12.2  jdolecek 	if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
   2222  1.12.12.2  jdolecek 		/* event not enabled */
   2223  1.12.12.2  jdolecek 		return;
   2224  1.12.12.2  jdolecek 
   2225  1.12.12.2  jdolecek 	length = sizeof(struct sctp_send_failed) + chk->send_size;
   2226  1.12.12.2  jdolecek 	MGETHDR(m_notify, M_DONTWAIT, MT_DATA);
   2227  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2228  1.12.12.2  jdolecek 		/* no space left */
   2229  1.12.12.2  jdolecek 		return;
   2230  1.12.12.2  jdolecek 	m_notify->m_len = 0;
   2231  1.12.12.2  jdolecek 	ssf = mtod(m_notify, struct sctp_send_failed *);
   2232  1.12.12.2  jdolecek 	ssf->ssf_type = SCTP_SEND_FAILED;
   2233  1.12.12.2  jdolecek 	if (error == SCTP_NOTIFY_DATAGRAM_UNSENT)
   2234  1.12.12.2  jdolecek 		ssf->ssf_flags = SCTP_DATA_UNSENT;
   2235  1.12.12.2  jdolecek 	else
   2236  1.12.12.2  jdolecek 		ssf->ssf_flags = SCTP_DATA_SENT;
   2237  1.12.12.2  jdolecek 	ssf->ssf_length = length;
   2238  1.12.12.2  jdolecek 	ssf->ssf_error = error;
   2239  1.12.12.2  jdolecek 	/* not exactly what the user sent in, but should be close :) */
   2240  1.12.12.2  jdolecek 	ssf->ssf_info.sinfo_stream = chk->rec.data.stream_number;
   2241  1.12.12.2  jdolecek 	ssf->ssf_info.sinfo_ssn = chk->rec.data.stream_seq;
   2242  1.12.12.2  jdolecek 	ssf->ssf_info.sinfo_flags = chk->rec.data.rcv_flags;
   2243  1.12.12.2  jdolecek 	ssf->ssf_info.sinfo_ppid = chk->rec.data.payloadtype;
   2244  1.12.12.2  jdolecek 	ssf->ssf_info.sinfo_context = chk->rec.data.context;
   2245  1.12.12.2  jdolecek 	ssf->ssf_info.sinfo_assoc_id = sctp_get_associd(stcb);
   2246  1.12.12.2  jdolecek 	ssf->ssf_assoc_id = sctp_get_associd(stcb);
   2247  1.12.12.2  jdolecek 	m_notify->m_next = chk->data;
   2248  1.12.12.2  jdolecek 	if (m_notify->m_next == NULL)
   2249  1.12.12.2  jdolecek 		m_notify->m_flags |= M_EOR | M_NOTIFICATION;
   2250  1.12.12.2  jdolecek 	else {
   2251  1.12.12.2  jdolecek 		struct mbuf *m;
   2252  1.12.12.2  jdolecek 		m_notify->m_flags |= M_NOTIFICATION;
   2253  1.12.12.2  jdolecek 		m = m_notify;
   2254  1.12.12.2  jdolecek 		while (m->m_next != NULL)
   2255  1.12.12.2  jdolecek 			m = m->m_next;
   2256  1.12.12.2  jdolecek 		m->m_flags |= M_EOR;
   2257  1.12.12.2  jdolecek 	}
   2258  1.12.12.2  jdolecek 	m_notify->m_pkthdr.len = length;
   2259  1.12.12.2  jdolecek 	m_reset_rcvif(m_notify);
   2260  1.12.12.2  jdolecek 	m_notify->m_len = sizeof(struct sctp_send_failed);
   2261  1.12.12.2  jdolecek 
   2262  1.12.12.2  jdolecek 	/* Steal off the mbuf */
   2263  1.12.12.2  jdolecek 	chk->data = NULL;
   2264  1.12.12.2  jdolecek 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
   2265  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
   2266  1.12.12.2  jdolecek 	    to->sa_family == AF_INET) {
   2267  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   2268  1.12.12.2  jdolecek 
   2269  1.12.12.2  jdolecek 		sin = satocsin(to);
   2270  1.12.12.2  jdolecek 		in6_sin_2_v4mapsin6(sin, &sin6);
   2271  1.12.12.2  jdolecek 		to = (struct sockaddr *)&sin6;
   2272  1.12.12.2  jdolecek 	}
   2273  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2274  1.12.12.2  jdolecek 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
   2275  1.12.12.2  jdolecek 						   &lsa6);
   2276  1.12.12.2  jdolecek 
   2277  1.12.12.2  jdolecek 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
   2278  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2279  1.12.12.2  jdolecek 		return;
   2280  1.12.12.2  jdolecek 	}
   2281  1.12.12.2  jdolecek 
   2282  1.12.12.2  jdolecek 	/* append to socket */
   2283  1.12.12.2  jdolecek 	SCTP_TCB_UNLOCK(stcb);
   2284  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(stcb->sctp_ep);
   2285  1.12.12.2  jdolecek 	SCTP_TCB_LOCK(stcb);
   2286  1.12.12.2  jdolecek 	if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
   2287  1.12.12.2  jdolecek 	    m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
   2288  1.12.12.2  jdolecek 		/* not enough room */
   2289  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2290  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2291  1.12.12.2  jdolecek 		return;
   2292  1.12.12.2  jdolecek 	}
   2293  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   2294  1.12.12.2  jdolecek 	   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
   2295  1.12.12.2  jdolecek 		if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
   2296  1.12.12.2  jdolecek 			stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2297  1.12.12.2  jdolecek 		}
   2298  1.12.12.2  jdolecek 	} else {
   2299  1.12.12.2  jdolecek 		stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2300  1.12.12.2  jdolecek 	}
   2301  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2302  1.12.12.2  jdolecek 	sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2303  1.12.12.2  jdolecek }
   2304  1.12.12.2  jdolecek 
   2305  1.12.12.2  jdolecek static void
   2306  1.12.12.2  jdolecek sctp_notify_adaption_layer(struct sctp_tcb *stcb,
   2307  1.12.12.2  jdolecek 			   u_int32_t error)
   2308  1.12.12.2  jdolecek {
   2309  1.12.12.2  jdolecek 	struct mbuf *m_notify;
   2310  1.12.12.2  jdolecek 	struct sctp_adaption_event *sai;
   2311  1.12.12.2  jdolecek 	struct sockaddr_in6 sin6, lsa6;
   2312  1.12.12.2  jdolecek 	const struct sockaddr *to;
   2313  1.12.12.2  jdolecek 
   2314  1.12.12.2  jdolecek 	if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_ADAPTIONEVNT))
   2315  1.12.12.2  jdolecek 		/* event not enabled */
   2316  1.12.12.2  jdolecek 		return;
   2317  1.12.12.2  jdolecek 
   2318  1.12.12.2  jdolecek 	MGETHDR(m_notify, M_DONTWAIT, MT_DATA);
   2319  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2320  1.12.12.2  jdolecek 		/* no space left */
   2321  1.12.12.2  jdolecek 		return;
   2322  1.12.12.2  jdolecek 	m_notify->m_len = 0;
   2323  1.12.12.2  jdolecek 	sai = mtod(m_notify, struct sctp_adaption_event *);
   2324  1.12.12.2  jdolecek 	sai->sai_type = SCTP_ADAPTION_INDICATION;
   2325  1.12.12.2  jdolecek 	sai->sai_flags = 0;
   2326  1.12.12.2  jdolecek 	sai->sai_length = sizeof(struct sctp_adaption_event);
   2327  1.12.12.2  jdolecek 	sai->sai_adaption_ind = error;
   2328  1.12.12.2  jdolecek 	sai->sai_assoc_id = sctp_get_associd(stcb);
   2329  1.12.12.2  jdolecek 
   2330  1.12.12.2  jdolecek 	m_notify->m_flags |= M_EOR | M_NOTIFICATION;
   2331  1.12.12.2  jdolecek 	m_notify->m_pkthdr.len = sizeof(struct sctp_adaption_event);
   2332  1.12.12.2  jdolecek 	m_reset_rcvif(m_notify);
   2333  1.12.12.2  jdolecek 	m_notify->m_len = sizeof(struct sctp_adaption_event);
   2334  1.12.12.2  jdolecek 	m_notify->m_next = NULL;
   2335  1.12.12.2  jdolecek 
   2336  1.12.12.2  jdolecek 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
   2337  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
   2338  1.12.12.2  jdolecek 	    (to->sa_family == AF_INET)) {
   2339  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   2340  1.12.12.2  jdolecek 
   2341  1.12.12.2  jdolecek 		sin = satocsin(to);
   2342  1.12.12.2  jdolecek 		in6_sin_2_v4mapsin6(sin, &sin6);
   2343  1.12.12.2  jdolecek 		to = (struct sockaddr *)&sin6;
   2344  1.12.12.2  jdolecek 	}
   2345  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2346  1.12.12.2  jdolecek 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
   2347  1.12.12.2  jdolecek 						   &lsa6);
   2348  1.12.12.2  jdolecek 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
   2349  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2350  1.12.12.2  jdolecek 		return;
   2351  1.12.12.2  jdolecek 	}
   2352  1.12.12.2  jdolecek 	/* append to socket */
   2353  1.12.12.2  jdolecek 	SCTP_TCB_UNLOCK(stcb);
   2354  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(stcb->sctp_ep);
   2355  1.12.12.2  jdolecek 	SCTP_TCB_LOCK(stcb);
   2356  1.12.12.2  jdolecek 	if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
   2357  1.12.12.2  jdolecek 	    m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
   2358  1.12.12.2  jdolecek 		/* not enough room */
   2359  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2360  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2361  1.12.12.2  jdolecek 		return;
   2362  1.12.12.2  jdolecek 	}
   2363  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   2364  1.12.12.2  jdolecek 	   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
   2365  1.12.12.2  jdolecek 		if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
   2366  1.12.12.2  jdolecek 			stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2367  1.12.12.2  jdolecek 		}
   2368  1.12.12.2  jdolecek 	} else {
   2369  1.12.12.2  jdolecek 		stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2370  1.12.12.2  jdolecek 	}
   2371  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2372  1.12.12.2  jdolecek 	sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2373  1.12.12.2  jdolecek }
   2374  1.12.12.2  jdolecek 
   2375  1.12.12.2  jdolecek static void
   2376  1.12.12.2  jdolecek sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
   2377  1.12.12.2  jdolecek 					u_int32_t error)
   2378  1.12.12.2  jdolecek {
   2379  1.12.12.2  jdolecek 	struct mbuf *m_notify;
   2380  1.12.12.2  jdolecek 	struct sctp_pdapi_event *pdapi;
   2381  1.12.12.2  jdolecek 	struct sockaddr_in6 sin6, lsa6;
   2382  1.12.12.2  jdolecek 	const struct sockaddr *to;
   2383  1.12.12.2  jdolecek 
   2384  1.12.12.2  jdolecek 	if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_PDAPIEVNT))
   2385  1.12.12.2  jdolecek 		/* event not enabled */
   2386  1.12.12.2  jdolecek 		return;
   2387  1.12.12.2  jdolecek 
   2388  1.12.12.2  jdolecek 	MGETHDR(m_notify, M_DONTWAIT, MT_DATA);
   2389  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2390  1.12.12.2  jdolecek 		/* no space left */
   2391  1.12.12.2  jdolecek 		return;
   2392  1.12.12.2  jdolecek 	m_notify->m_len = 0;
   2393  1.12.12.2  jdolecek 	pdapi = mtod(m_notify, struct sctp_pdapi_event *);
   2394  1.12.12.2  jdolecek 	pdapi->pdapi_type = SCTP_PARTIAL_DELIVERY_EVENT;
   2395  1.12.12.2  jdolecek 	pdapi->pdapi_flags = 0;
   2396  1.12.12.2  jdolecek 	pdapi->pdapi_length = sizeof(struct sctp_pdapi_event);
   2397  1.12.12.2  jdolecek 	pdapi->pdapi_indication = error;
   2398  1.12.12.2  jdolecek 	pdapi->pdapi_assoc_id = sctp_get_associd(stcb);
   2399  1.12.12.2  jdolecek 
   2400  1.12.12.2  jdolecek 	m_notify->m_flags |= M_EOR | M_NOTIFICATION;
   2401  1.12.12.2  jdolecek 	m_notify->m_pkthdr.len = sizeof(struct sctp_pdapi_event);
   2402  1.12.12.2  jdolecek 	m_reset_rcvif(m_notify);
   2403  1.12.12.2  jdolecek 	m_notify->m_len = sizeof(struct sctp_pdapi_event);
   2404  1.12.12.2  jdolecek 	m_notify->m_next = NULL;
   2405  1.12.12.2  jdolecek 
   2406  1.12.12.2  jdolecek 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
   2407  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
   2408  1.12.12.2  jdolecek 	    (to->sa_family == AF_INET)) {
   2409  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   2410  1.12.12.2  jdolecek 
   2411  1.12.12.2  jdolecek 		sin = satocsin(to);
   2412  1.12.12.2  jdolecek 		in6_sin_2_v4mapsin6(sin, &sin6);
   2413  1.12.12.2  jdolecek 		to = (struct sockaddr *)&sin6;
   2414  1.12.12.2  jdolecek 	}
   2415  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2416  1.12.12.2  jdolecek 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
   2417  1.12.12.2  jdolecek 						   &lsa6);
   2418  1.12.12.2  jdolecek 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
   2419  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2420  1.12.12.2  jdolecek 		return;
   2421  1.12.12.2  jdolecek 	}
   2422  1.12.12.2  jdolecek 	/* append to socket */
   2423  1.12.12.2  jdolecek 	SCTP_TCB_UNLOCK(stcb);
   2424  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(stcb->sctp_ep);
   2425  1.12.12.2  jdolecek 	SCTP_TCB_LOCK(stcb);
   2426  1.12.12.2  jdolecek 	if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
   2427  1.12.12.2  jdolecek 	    m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
   2428  1.12.12.2  jdolecek 		/* not enough room */
   2429  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2430  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2431  1.12.12.2  jdolecek 		return;
   2432  1.12.12.2  jdolecek 	}
   2433  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   2434  1.12.12.2  jdolecek 	   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
   2435  1.12.12.2  jdolecek 		if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
   2436  1.12.12.2  jdolecek 			stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2437  1.12.12.2  jdolecek 		}
   2438  1.12.12.2  jdolecek 	} else {
   2439  1.12.12.2  jdolecek 		stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2440  1.12.12.2  jdolecek 	}
   2441  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2442  1.12.12.2  jdolecek 	sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2443  1.12.12.2  jdolecek }
   2444  1.12.12.2  jdolecek 
   2445  1.12.12.2  jdolecek static void
   2446  1.12.12.2  jdolecek sctp_notify_shutdown_event(struct sctp_tcb *stcb)
   2447  1.12.12.2  jdolecek {
   2448  1.12.12.2  jdolecek 	struct mbuf *m_notify;
   2449  1.12.12.2  jdolecek 	struct sctp_shutdown_event *sse;
   2450  1.12.12.2  jdolecek 	struct sockaddr_in6 sin6, lsa6;
   2451  1.12.12.2  jdolecek 	const struct sockaddr *to;
   2452  1.12.12.2  jdolecek 
   2453  1.12.12.2  jdolecek 	/*
   2454  1.12.12.2  jdolecek 	 * For TCP model AND UDP connected sockets we will send
   2455  1.12.12.2  jdolecek 	 * an error up when an SHUTDOWN completes
   2456  1.12.12.2  jdolecek 	 */
   2457  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   2458  1.12.12.2  jdolecek 	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   2459  1.12.12.2  jdolecek 		/* mark socket closed for read/write and wakeup! */
   2460  1.12.12.2  jdolecek 		socantrcvmore(stcb->sctp_socket);
   2461  1.12.12.2  jdolecek 		socantsendmore(stcb->sctp_socket);
   2462  1.12.12.2  jdolecek 	}
   2463  1.12.12.2  jdolecek 
   2464  1.12.12.2  jdolecek 	if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
   2465  1.12.12.2  jdolecek 		/* event not enabled */
   2466  1.12.12.2  jdolecek 		return;
   2467  1.12.12.2  jdolecek 
   2468  1.12.12.2  jdolecek 	MGETHDR(m_notify, M_DONTWAIT, MT_DATA);
   2469  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2470  1.12.12.2  jdolecek 		/* no space left */
   2471  1.12.12.2  jdolecek 		return;
   2472  1.12.12.2  jdolecek 	m_notify->m_len = 0;
   2473  1.12.12.2  jdolecek 	sse = mtod(m_notify, struct sctp_shutdown_event *);
   2474  1.12.12.2  jdolecek 	sse->sse_type = SCTP_SHUTDOWN_EVENT;
   2475  1.12.12.2  jdolecek 	sse->sse_flags = 0;
   2476  1.12.12.2  jdolecek 	sse->sse_length = sizeof(struct sctp_shutdown_event);
   2477  1.12.12.2  jdolecek 	sse->sse_assoc_id = sctp_get_associd(stcb);
   2478  1.12.12.2  jdolecek 
   2479  1.12.12.2  jdolecek 	m_notify->m_flags |= M_EOR | M_NOTIFICATION;
   2480  1.12.12.2  jdolecek 	m_notify->m_pkthdr.len = sizeof(struct sctp_shutdown_event);
   2481  1.12.12.2  jdolecek 	m_reset_rcvif(m_notify);
   2482  1.12.12.2  jdolecek 	m_notify->m_len = sizeof(struct sctp_shutdown_event);
   2483  1.12.12.2  jdolecek 	m_notify->m_next = NULL;
   2484  1.12.12.2  jdolecek 
   2485  1.12.12.2  jdolecek 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
   2486  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
   2487  1.12.12.2  jdolecek 	    to->sa_family == AF_INET) {
   2488  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   2489  1.12.12.2  jdolecek 
   2490  1.12.12.2  jdolecek 		sin = satocsin(to);
   2491  1.12.12.2  jdolecek 		in6_sin_2_v4mapsin6(sin, &sin6);
   2492  1.12.12.2  jdolecek 		to = (struct sockaddr *)&sin6;
   2493  1.12.12.2  jdolecek 	}
   2494  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2495  1.12.12.2  jdolecek 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
   2496  1.12.12.2  jdolecek 	    &lsa6);
   2497  1.12.12.2  jdolecek 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
   2498  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2499  1.12.12.2  jdolecek 		return;
   2500  1.12.12.2  jdolecek 	}
   2501  1.12.12.2  jdolecek 	/* append to socket */
   2502  1.12.12.2  jdolecek 	SCTP_TCB_UNLOCK(stcb);
   2503  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(stcb->sctp_ep);
   2504  1.12.12.2  jdolecek 	SCTP_TCB_LOCK(stcb);
   2505  1.12.12.2  jdolecek 	if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
   2506  1.12.12.2  jdolecek 	    m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
   2507  1.12.12.2  jdolecek 		/* not enough room */
   2508  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2509  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2510  1.12.12.2  jdolecek 		return;
   2511  1.12.12.2  jdolecek 	}
   2512  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   2513  1.12.12.2  jdolecek 	   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
   2514  1.12.12.2  jdolecek 		if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
   2515  1.12.12.2  jdolecek 			stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2516  1.12.12.2  jdolecek 		}
   2517  1.12.12.2  jdolecek 	} else {
   2518  1.12.12.2  jdolecek 		stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2519  1.12.12.2  jdolecek 	}
   2520  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2521  1.12.12.2  jdolecek 	sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2522  1.12.12.2  jdolecek }
   2523  1.12.12.2  jdolecek 
   2524  1.12.12.2  jdolecek static void
   2525  1.12.12.2  jdolecek sctp_notify_stream_reset(struct sctp_tcb *stcb,
   2526  1.12.12.2  jdolecek     int number_entries, uint16_t *list, int flag)
   2527  1.12.12.2  jdolecek {
   2528  1.12.12.2  jdolecek 	struct mbuf *m_notify;
   2529  1.12.12.2  jdolecek 	struct sctp_stream_reset_event *strreset;
   2530  1.12.12.2  jdolecek 	struct sockaddr_in6 sin6, lsa6;
   2531  1.12.12.2  jdolecek 	const struct sockaddr *to;
   2532  1.12.12.2  jdolecek 	int len;
   2533  1.12.12.2  jdolecek 
   2534  1.12.12.2  jdolecek 	if (!(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_STREAM_RESETEVNT))
   2535  1.12.12.2  jdolecek 		/* event not enabled */
   2536  1.12.12.2  jdolecek 		return;
   2537  1.12.12.2  jdolecek 
   2538  1.12.12.2  jdolecek 	MGETHDR(m_notify, M_DONTWAIT, MT_DATA);
   2539  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2540  1.12.12.2  jdolecek 		/* no space left */
   2541  1.12.12.2  jdolecek 		return;
   2542  1.12.12.2  jdolecek 	m_notify->m_len = 0;
   2543  1.12.12.2  jdolecek 	len = sizeof(struct sctp_stream_reset_event) + (number_entries * sizeof(uint16_t));
   2544  1.12.12.2  jdolecek 	if (len > M_TRAILINGSPACE(m_notify)) {
   2545  1.12.12.2  jdolecek 		MCLGET(m_notify, M_WAIT);
   2546  1.12.12.2  jdolecek 	}
   2547  1.12.12.2  jdolecek 	if (m_notify == NULL)
   2548  1.12.12.2  jdolecek 		/* no clusters */
   2549  1.12.12.2  jdolecek 		return;
   2550  1.12.12.2  jdolecek 
   2551  1.12.12.2  jdolecek 	if (len > M_TRAILINGSPACE(m_notify)) {
   2552  1.12.12.2  jdolecek 		/* never enough room */
   2553  1.12.12.2  jdolecek 		m_freem(m_notify);
   2554  1.12.12.2  jdolecek 		return;
   2555  1.12.12.2  jdolecek 	}
   2556  1.12.12.2  jdolecek 	strreset = mtod(m_notify, struct sctp_stream_reset_event *);
   2557  1.12.12.2  jdolecek 	strreset->strreset_type = SCTP_STREAM_RESET_EVENT;
   2558  1.12.12.2  jdolecek 	if (number_entries == 0) {
   2559  1.12.12.2  jdolecek 		strreset->strreset_flags = flag | SCTP_STRRESET_ALL_STREAMS;
   2560  1.12.12.2  jdolecek 	} else {
   2561  1.12.12.2  jdolecek 		strreset->strreset_flags = flag | SCTP_STRRESET_STREAM_LIST;
   2562  1.12.12.2  jdolecek 	}
   2563  1.12.12.2  jdolecek 	strreset->strreset_length = len;
   2564  1.12.12.2  jdolecek 	strreset->strreset_assoc_id = sctp_get_associd(stcb);
   2565  1.12.12.2  jdolecek 	if (number_entries) {
   2566  1.12.12.2  jdolecek 		int i;
   2567  1.12.12.2  jdolecek 		for (i=0; i<number_entries; i++) {
   2568  1.12.12.2  jdolecek 			strreset->strreset_list[i] = list[i];
   2569  1.12.12.2  jdolecek 		}
   2570  1.12.12.2  jdolecek 	}
   2571  1.12.12.2  jdolecek 	m_notify->m_flags |= M_EOR | M_NOTIFICATION;
   2572  1.12.12.2  jdolecek 	m_notify->m_pkthdr.len = len;
   2573  1.12.12.2  jdolecek 	m_reset_rcvif(m_notify);
   2574  1.12.12.2  jdolecek 	m_notify->m_len = len;
   2575  1.12.12.2  jdolecek 	m_notify->m_next = NULL;
   2576  1.12.12.2  jdolecek 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
   2577  1.12.12.2  jdolecek 		/* no space */
   2578  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2579  1.12.12.2  jdolecek 		return;
   2580  1.12.12.2  jdolecek 	}
   2581  1.12.12.2  jdolecek 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
   2582  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
   2583  1.12.12.2  jdolecek 	    to->sa_family == AF_INET) {
   2584  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   2585  1.12.12.2  jdolecek 
   2586  1.12.12.2  jdolecek 		sin = satocsin(to);
   2587  1.12.12.2  jdolecek 		in6_sin_2_v4mapsin6(sin, &sin6);
   2588  1.12.12.2  jdolecek 		to = (struct sockaddr *)&sin6;
   2589  1.12.12.2  jdolecek 	}
   2590  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2591  1.12.12.2  jdolecek 	to = (const struct sockaddr *) sctp_recover_scope((const struct sockaddr_in6 *)to,
   2592  1.12.12.2  jdolecek 	    &lsa6);
   2593  1.12.12.2  jdolecek 	/* append to socket */
   2594  1.12.12.2  jdolecek 	SCTP_TCB_UNLOCK(stcb);
   2595  1.12.12.2  jdolecek 	SCTP_INP_WLOCK(stcb->sctp_ep);
   2596  1.12.12.2  jdolecek 	SCTP_TCB_LOCK(stcb);
   2597  1.12.12.2  jdolecek 	if (!sbappendaddr_nocheck(&stcb->sctp_socket->so_rcv, to,
   2598  1.12.12.2  jdolecek 	    m_notify, NULL, stcb->asoc.my_vtag, stcb->sctp_ep)) {
   2599  1.12.12.2  jdolecek 		/* not enough room */
   2600  1.12.12.2  jdolecek 		sctp_m_freem(m_notify);
   2601  1.12.12.2  jdolecek 		SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2602  1.12.12.2  jdolecek 		return;
   2603  1.12.12.2  jdolecek 	}
   2604  1.12.12.2  jdolecek 	if (((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
   2605  1.12.12.2  jdolecek 	   ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)){
   2606  1.12.12.2  jdolecek 		if (sctp_add_to_socket_q(stcb->sctp_ep, stcb)) {
   2607  1.12.12.2  jdolecek 			stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2608  1.12.12.2  jdolecek 		}
   2609  1.12.12.2  jdolecek 	} else {
   2610  1.12.12.2  jdolecek 		stcb->asoc.my_rwnd_control_len += sizeof(struct mbuf);
   2611  1.12.12.2  jdolecek 	}
   2612  1.12.12.2  jdolecek 	SCTP_INP_WUNLOCK(stcb->sctp_ep);
   2613  1.12.12.2  jdolecek 	sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
   2614  1.12.12.2  jdolecek }
   2615  1.12.12.2  jdolecek 
   2616  1.12.12.2  jdolecek 
   2617  1.12.12.2  jdolecek void
   2618  1.12.12.2  jdolecek sctp_ulp_notify(u_int32_t notification, struct sctp_tcb *stcb,
   2619  1.12.12.2  jdolecek 		u_int32_t error, void *data)
   2620  1.12.12.2  jdolecek {
   2621  1.12.12.2  jdolecek 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
   2622  1.12.12.2  jdolecek 		/* No notifications up when we are in a no socket state */
   2623  1.12.12.2  jdolecek 		return;
   2624  1.12.12.2  jdolecek 	}
   2625  1.12.12.2  jdolecek 	if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
   2626  1.12.12.2  jdolecek 		/* Can't send up to a closed socket any notifications */
   2627  1.12.12.2  jdolecek 		return;
   2628  1.12.12.2  jdolecek 	}
   2629  1.12.12.2  jdolecek 	switch (notification) {
   2630  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASSOC_UP:
   2631  1.12.12.2  jdolecek 		sctp_notify_assoc_change(SCTP_COMM_UP, stcb, error);
   2632  1.12.12.2  jdolecek 		break;
   2633  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASSOC_DOWN:
   2634  1.12.12.2  jdolecek 		sctp_notify_assoc_change(SCTP_SHUTDOWN_COMP, stcb, error);
   2635  1.12.12.2  jdolecek 		break;
   2636  1.12.12.2  jdolecek 	case SCTP_NOTIFY_INTERFACE_DOWN:
   2637  1.12.12.2  jdolecek 	{
   2638  1.12.12.2  jdolecek 		struct sctp_nets *net;
   2639  1.12.12.2  jdolecek 		net = (struct sctp_nets *)data;
   2640  1.12.12.2  jdolecek 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_UNREACHABLE,
   2641  1.12.12.2  jdolecek 		    rtcache_getdst(&net->ro), error);
   2642  1.12.12.2  jdolecek 		break;
   2643  1.12.12.2  jdolecek 	}
   2644  1.12.12.2  jdolecek 	case SCTP_NOTIFY_INTERFACE_UP:
   2645  1.12.12.2  jdolecek 	{
   2646  1.12.12.2  jdolecek 		struct sctp_nets *net;
   2647  1.12.12.2  jdolecek 		net = (struct sctp_nets *)data;
   2648  1.12.12.2  jdolecek 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_AVAILABLE,
   2649  1.12.12.2  jdolecek 		    rtcache_getdst(&net->ro), error);
   2650  1.12.12.2  jdolecek 		break;
   2651  1.12.12.2  jdolecek 	}
   2652  1.12.12.2  jdolecek 	case SCTP_NOTIFY_INTERFACE_CONFIRMED:
   2653  1.12.12.2  jdolecek 	{
   2654  1.12.12.2  jdolecek 		struct sctp_nets *net;
   2655  1.12.12.2  jdolecek 		net = (struct sctp_nets *)data;
   2656  1.12.12.2  jdolecek 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_CONFIRMED,
   2657  1.12.12.2  jdolecek 		    rtcache_getdst(&net->ro), error);
   2658  1.12.12.2  jdolecek 		break;
   2659  1.12.12.2  jdolecek 	}
   2660  1.12.12.2  jdolecek 	case SCTP_NOTIFY_DG_FAIL:
   2661  1.12.12.2  jdolecek 		sctp_notify_send_failed(stcb, error,
   2662  1.12.12.2  jdolecek 		    (struct sctp_tmit_chunk *)data);
   2663  1.12.12.2  jdolecek 		break;
   2664  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ADAPTION_INDICATION:
   2665  1.12.12.2  jdolecek 		/* Here the error is the adaption indication */
   2666  1.12.12.2  jdolecek 		sctp_notify_adaption_layer(stcb, error);
   2667  1.12.12.2  jdolecek 		break;
   2668  1.12.12.2  jdolecek 	case SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION:
   2669  1.12.12.2  jdolecek 		sctp_notify_partial_delivery_indication(stcb, error);
   2670  1.12.12.2  jdolecek 		break;
   2671  1.12.12.2  jdolecek 	case SCTP_NOTIFY_STRDATA_ERR:
   2672  1.12.12.2  jdolecek 		break;
   2673  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASSOC_ABORTED:
   2674  1.12.12.2  jdolecek 		sctp_notify_assoc_change(SCTP_COMM_LOST, stcb, error);
   2675  1.12.12.2  jdolecek 		break;
   2676  1.12.12.2  jdolecek 	case SCTP_NOTIFY_PEER_OPENED_STREAM:
   2677  1.12.12.2  jdolecek 		break;
   2678  1.12.12.2  jdolecek 	case SCTP_NOTIFY_STREAM_OPENED_OK:
   2679  1.12.12.2  jdolecek 		break;
   2680  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASSOC_RESTART:
   2681  1.12.12.2  jdolecek 		sctp_notify_assoc_change(SCTP_RESTART, stcb, error);
   2682  1.12.12.2  jdolecek 		break;
   2683  1.12.12.2  jdolecek 	case SCTP_NOTIFY_HB_RESP:
   2684  1.12.12.2  jdolecek 		break;
   2685  1.12.12.2  jdolecek 	case SCTP_NOTIFY_STR_RESET_SEND:
   2686  1.12.12.2  jdolecek 		sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_OUTBOUND_STR);
   2687  1.12.12.2  jdolecek 		break;
   2688  1.12.12.2  jdolecek 	case SCTP_NOTIFY_STR_RESET_RECV:
   2689  1.12.12.2  jdolecek 		sctp_notify_stream_reset(stcb, error, ((uint16_t *)data), SCTP_STRRESET_INBOUND_STR);
   2690  1.12.12.2  jdolecek 		break;
   2691  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASCONF_ADD_IP:
   2692  1.12.12.2  jdolecek 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_ADDED, data,
   2693  1.12.12.2  jdolecek 		    error);
   2694  1.12.12.2  jdolecek 		break;
   2695  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASCONF_DELETE_IP:
   2696  1.12.12.2  jdolecek 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_REMOVED, data,
   2697  1.12.12.2  jdolecek 		    error);
   2698  1.12.12.2  jdolecek 		break;
   2699  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASCONF_SET_PRIMARY:
   2700  1.12.12.2  jdolecek 		sctp_notify_peer_addr_change(stcb, SCTP_ADDR_MADE_PRIM, data,
   2701  1.12.12.2  jdolecek 		    error);
   2702  1.12.12.2  jdolecek 		break;
   2703  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASCONF_SUCCESS:
   2704  1.12.12.2  jdolecek 		break;
   2705  1.12.12.2  jdolecek 	case SCTP_NOTIFY_ASCONF_FAILED:
   2706  1.12.12.2  jdolecek 		break;
   2707  1.12.12.2  jdolecek 	case SCTP_NOTIFY_PEER_SHUTDOWN:
   2708  1.12.12.2  jdolecek 		sctp_notify_shutdown_event(stcb);
   2709  1.12.12.2  jdolecek 		break;
   2710  1.12.12.2  jdolecek 	default:
   2711  1.12.12.2  jdolecek #ifdef SCTP_DEBUG
   2712  1.12.12.2  jdolecek 		if (sctp_debug_on & SCTP_DEBUG_UTIL1) {
   2713  1.12.12.2  jdolecek 			printf("NOTIFY: unknown notification %xh (%u)\n",
   2714  1.12.12.2  jdolecek 			    notification, notification);
   2715  1.12.12.2  jdolecek 		}
   2716  1.12.12.2  jdolecek #endif /* SCTP_DEBUG */
   2717  1.12.12.2  jdolecek 		break;
   2718  1.12.12.2  jdolecek 	} /* end switch */
   2719  1.12.12.2  jdolecek }
   2720  1.12.12.2  jdolecek 
   2721  1.12.12.2  jdolecek void
   2722  1.12.12.2  jdolecek sctp_report_all_outbound(struct sctp_tcb *stcb)
   2723  1.12.12.2  jdolecek {
   2724  1.12.12.2  jdolecek 	struct sctp_association *asoc;
   2725  1.12.12.2  jdolecek 	struct sctp_stream_out *outs;
   2726  1.12.12.2  jdolecek 	struct sctp_tmit_chunk *chk;
   2727  1.12.12.2  jdolecek 
   2728  1.12.12.2  jdolecek 	asoc = &stcb->asoc;
   2729  1.12.12.2  jdolecek 
   2730  1.12.12.2  jdolecek 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
   2731  1.12.12.2  jdolecek 		return;
   2732  1.12.12.2  jdolecek 	}
   2733  1.12.12.2  jdolecek 	/* now through all the gunk freeing chunks */
   2734  1.12.12.2  jdolecek 	TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
   2735  1.12.12.2  jdolecek 		/* now clean up any chunks here */
   2736  1.12.12.2  jdolecek 		chk = TAILQ_FIRST(&outs->outqueue);
   2737  1.12.12.2  jdolecek 		while (chk) {
   2738  1.12.12.2  jdolecek 			stcb->asoc.stream_queue_cnt--;
   2739  1.12.12.2  jdolecek 			TAILQ_REMOVE(&outs->outqueue, chk, sctp_next);
   2740  1.12.12.2  jdolecek 			sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
   2741  1.12.12.2  jdolecek 			    SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
   2742  1.12.12.2  jdolecek 			if (chk->data) {
   2743  1.12.12.2  jdolecek 				sctp_m_freem(chk->data);
   2744  1.12.12.2  jdolecek 				chk->data = NULL;
   2745  1.12.12.2  jdolecek 			}
   2746  1.12.12.2  jdolecek 			if (chk->whoTo)
   2747  1.12.12.2  jdolecek 				sctp_free_remote_addr(chk->whoTo);
   2748  1.12.12.2  jdolecek 			chk->whoTo = NULL;
   2749  1.12.12.2  jdolecek 			chk->asoc = NULL;
   2750  1.12.12.2  jdolecek 			/* Free the chunk */
   2751  1.12.12.2  jdolecek 			SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
   2752  1.12.12.2  jdolecek 			sctppcbinfo.ipi_count_chunk--;
   2753  1.12.12.2  jdolecek 			if ((int)sctppcbinfo.ipi_count_chunk < 0) {
   2754  1.12.12.2  jdolecek 				panic("Chunk count is negative");
   2755  1.12.12.2  jdolecek 			}
   2756  1.12.12.2  jdolecek 			sctppcbinfo.ipi_gencnt_chunk++;
   2757  1.12.12.2  jdolecek 			chk = TAILQ_FIRST(&outs->outqueue);
   2758  1.12.12.2  jdolecek 		}
   2759  1.12.12.2  jdolecek 	}
   2760  1.12.12.2  jdolecek 	/* pending send queue SHOULD be empty */
   2761  1.12.12.2  jdolecek 	if (!TAILQ_EMPTY(&asoc->send_queue)) {
   2762  1.12.12.2  jdolecek 		chk = TAILQ_FIRST(&asoc->send_queue);
   2763  1.12.12.2  jdolecek 		while (chk) {
   2764  1.12.12.2  jdolecek 			TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
   2765  1.12.12.2  jdolecek 			sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk);
   2766  1.12.12.2  jdolecek 			if (chk->data) {
   2767  1.12.12.2  jdolecek 				sctp_m_freem(chk->data);
   2768  1.12.12.2  jdolecek 				chk->data = NULL;
   2769  1.12.12.2  jdolecek 			}
   2770  1.12.12.2  jdolecek 			if (chk->whoTo)
   2771  1.12.12.2  jdolecek 				sctp_free_remote_addr(chk->whoTo);
   2772  1.12.12.2  jdolecek 			chk->whoTo = NULL;
   2773  1.12.12.2  jdolecek 			SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
   2774  1.12.12.2  jdolecek 			sctppcbinfo.ipi_count_chunk--;
   2775  1.12.12.2  jdolecek 			if ((int)sctppcbinfo.ipi_count_chunk < 0) {
   2776  1.12.12.2  jdolecek 				panic("Chunk count is negative");
   2777  1.12.12.2  jdolecek 			}
   2778  1.12.12.2  jdolecek 			sctppcbinfo.ipi_gencnt_chunk++;
   2779  1.12.12.2  jdolecek 			chk = TAILQ_FIRST(&asoc->send_queue);
   2780  1.12.12.2  jdolecek 		}
   2781  1.12.12.2  jdolecek 	}
   2782  1.12.12.2  jdolecek 	/* sent queue SHOULD be empty */
   2783  1.12.12.2  jdolecek 	if (!TAILQ_EMPTY(&asoc->sent_queue)) {
   2784  1.12.12.2  jdolecek 		chk = TAILQ_FIRST(&asoc->sent_queue);
   2785  1.12.12.2  jdolecek 		while (chk) {
   2786  1.12.12.2  jdolecek 			TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
   2787  1.12.12.2  jdolecek 			sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
   2788  1.12.12.2  jdolecek 			    SCTP_NOTIFY_DATAGRAM_SENT, chk);
   2789  1.12.12.2  jdolecek 			if (chk->data) {
   2790  1.12.12.2  jdolecek 				sctp_m_freem(chk->data);
   2791  1.12.12.2  jdolecek 				chk->data = NULL;
   2792  1.12.12.2  jdolecek 			}
   2793  1.12.12.2  jdolecek 			if (chk->whoTo)
   2794  1.12.12.2  jdolecek 				sctp_free_remote_addr(chk->whoTo);
   2795  1.12.12.2  jdolecek 			chk->whoTo = NULL;
   2796  1.12.12.2  jdolecek 			SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, chk);
   2797  1.12.12.2  jdolecek 			sctppcbinfo.ipi_count_chunk--;
   2798  1.12.12.2  jdolecek 			if ((int)sctppcbinfo.ipi_count_chunk < 0) {
   2799  1.12.12.2  jdolecek 				panic("Chunk count is negative");
   2800  1.12.12.2  jdolecek 			}
   2801  1.12.12.2  jdolecek 			sctppcbinfo.ipi_gencnt_chunk++;
   2802  1.12.12.2  jdolecek 			chk = TAILQ_FIRST(&asoc->sent_queue);
   2803  1.12.12.2  jdolecek 		}
   2804  1.12.12.2  jdolecek 	}
   2805  1.12.12.2  jdolecek }
   2806  1.12.12.2  jdolecek 
   2807  1.12.12.2  jdolecek void
   2808  1.12.12.2  jdolecek sctp_abort_notification(struct sctp_tcb *stcb, int error)
   2809  1.12.12.2  jdolecek {
   2810  1.12.12.2  jdolecek 
   2811  1.12.12.2  jdolecek 	if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
   2812  1.12.12.2  jdolecek 		return;
   2813  1.12.12.2  jdolecek 	}
   2814  1.12.12.2  jdolecek 	/* Tell them we lost the asoc */
   2815  1.12.12.2  jdolecek 	sctp_report_all_outbound(stcb);
   2816  1.12.12.2  jdolecek 	sctp_ulp_notify(SCTP_NOTIFY_ASSOC_ABORTED, stcb, error, NULL);
   2817  1.12.12.2  jdolecek }
   2818  1.12.12.2  jdolecek 
   2819  1.12.12.2  jdolecek void
   2820  1.12.12.2  jdolecek sctp_abort_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   2821  1.12.12.2  jdolecek     struct mbuf *m, int iphlen, struct sctphdr *sh, struct mbuf *op_err)
   2822  1.12.12.2  jdolecek {
   2823  1.12.12.2  jdolecek 	u_int32_t vtag;
   2824  1.12.12.2  jdolecek 
   2825  1.12.12.2  jdolecek 	vtag = 0;
   2826  1.12.12.2  jdolecek 	if (stcb != NULL) {
   2827  1.12.12.2  jdolecek 		/* We have a TCB to abort, send notification too */
   2828  1.12.12.2  jdolecek 		vtag = stcb->asoc.peer_vtag;
   2829  1.12.12.2  jdolecek 		sctp_abort_notification(stcb, 0);
   2830  1.12.12.2  jdolecek 	}
   2831  1.12.12.2  jdolecek 	sctp_send_abort(m, iphlen, sh, vtag, op_err);
   2832  1.12.12.2  jdolecek 	if (stcb != NULL) {
   2833  1.12.12.2  jdolecek 		/* Ok, now lets free it */
   2834  1.12.12.2  jdolecek 		sctp_free_assoc(inp, stcb);
   2835  1.12.12.2  jdolecek 	} else {
   2836  1.12.12.2  jdolecek 		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
   2837  1.12.12.2  jdolecek 			if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
   2838  1.12.12.2  jdolecek 				sctp_inpcb_free(inp, 1);
   2839  1.12.12.2  jdolecek 			}
   2840  1.12.12.2  jdolecek 		}
   2841  1.12.12.2  jdolecek 	}
   2842  1.12.12.2  jdolecek }
   2843  1.12.12.2  jdolecek 
   2844  1.12.12.2  jdolecek void
   2845  1.12.12.2  jdolecek sctp_abort_an_association(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
   2846  1.12.12.2  jdolecek     int error, struct mbuf *op_err)
   2847  1.12.12.2  jdolecek {
   2848  1.12.12.2  jdolecek 
   2849  1.12.12.2  jdolecek 	if (stcb == NULL) {
   2850  1.12.12.2  jdolecek 		/* Got to have a TCB */
   2851  1.12.12.2  jdolecek 		if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
   2852  1.12.12.2  jdolecek 			if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
   2853  1.12.12.2  jdolecek 				sctp_inpcb_free(inp, 1);
   2854  1.12.12.2  jdolecek 			}
   2855  1.12.12.2  jdolecek 		}
   2856  1.12.12.2  jdolecek 		return;
   2857  1.12.12.2  jdolecek 	}
   2858  1.12.12.2  jdolecek 	/* notify the ulp */
   2859  1.12.12.2  jdolecek 	if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)
   2860  1.12.12.2  jdolecek 		sctp_abort_notification(stcb, error);
   2861  1.12.12.2  jdolecek 	/* notify the peer */
   2862  1.12.12.2  jdolecek 	sctp_send_abort_tcb(stcb, op_err);
   2863  1.12.12.2  jdolecek 	/* now free the asoc */
   2864  1.12.12.2  jdolecek 	sctp_free_assoc(inp, stcb);
   2865  1.12.12.2  jdolecek }
   2866  1.12.12.2  jdolecek 
   2867  1.12.12.2  jdolecek void
   2868  1.12.12.2  jdolecek sctp_handle_ootb(struct mbuf *m, int iphlen, int offset, struct sctphdr *sh,
   2869  1.12.12.2  jdolecek     struct sctp_inpcb *inp, struct mbuf *op_err)
   2870  1.12.12.2  jdolecek {
   2871  1.12.12.2  jdolecek 	struct sctp_chunkhdr *ch, chunk_buf;
   2872  1.12.12.2  jdolecek 	unsigned int chk_length;
   2873  1.12.12.2  jdolecek 
   2874  1.12.12.2  jdolecek 	/* Generate a TO address for future reference */
   2875  1.12.12.2  jdolecek 	if (inp && (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
   2876  1.12.12.2  jdolecek 		if (LIST_FIRST(&inp->sctp_asoc_list) == NULL) {
   2877  1.12.12.2  jdolecek 			sctp_inpcb_free(inp, 1);
   2878  1.12.12.2  jdolecek 		}
   2879  1.12.12.2  jdolecek 	}
   2880  1.12.12.2  jdolecek 	ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
   2881  1.12.12.2  jdolecek 	    sizeof(*ch), (u_int8_t *)&chunk_buf);
   2882  1.12.12.2  jdolecek 	while (ch != NULL) {
   2883  1.12.12.2  jdolecek 		chk_length = ntohs(ch->chunk_length);
   2884  1.12.12.2  jdolecek 		if (chk_length < sizeof(*ch)) {
   2885  1.12.12.2  jdolecek 			/* break to abort land */
   2886  1.12.12.2  jdolecek 			break;
   2887  1.12.12.2  jdolecek 		}
   2888  1.12.12.2  jdolecek 		switch (ch->chunk_type) {
   2889  1.12.12.2  jdolecek 		case SCTP_PACKET_DROPPED:
   2890  1.12.12.2  jdolecek 			/* we don't respond to pkt-dropped */
   2891  1.12.12.2  jdolecek 			return;
   2892  1.12.12.2  jdolecek 		case SCTP_ABORT_ASSOCIATION:
   2893  1.12.12.2  jdolecek 			/* we don't respond with an ABORT to an ABORT */
   2894  1.12.12.2  jdolecek 			return;
   2895  1.12.12.2  jdolecek 		case SCTP_SHUTDOWN_COMPLETE:
   2896  1.12.12.2  jdolecek 			/*
   2897  1.12.12.2  jdolecek 			 * we ignore it since we are not waiting for it
   2898  1.12.12.2  jdolecek 			 * and peer is gone
   2899  1.12.12.2  jdolecek 			 */
   2900  1.12.12.2  jdolecek 			return;
   2901  1.12.12.2  jdolecek 		case SCTP_SHUTDOWN_ACK:
   2902  1.12.12.2  jdolecek 			sctp_send_shutdown_complete2(m, iphlen, sh);
   2903  1.12.12.2  jdolecek 			return;
   2904  1.12.12.2  jdolecek 		default:
   2905  1.12.12.2  jdolecek 			break;
   2906  1.12.12.2  jdolecek 		}
   2907  1.12.12.2  jdolecek 		offset += SCTP_SIZE32(chk_length);
   2908  1.12.12.2  jdolecek 		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
   2909  1.12.12.2  jdolecek 		    sizeof(*ch), (u_int8_t *)&chunk_buf);
   2910  1.12.12.2  jdolecek 	}
   2911  1.12.12.2  jdolecek 	sctp_send_abort(m, iphlen, sh, 0, op_err);
   2912  1.12.12.2  jdolecek }
   2913  1.12.12.2  jdolecek 
   2914  1.12.12.2  jdolecek /*
   2915  1.12.12.2  jdolecek  * check the inbound datagram to make sure there is not an abort
   2916  1.12.12.2  jdolecek  * inside it, if there is return 1, else return 0.
   2917  1.12.12.2  jdolecek  */
   2918  1.12.12.2  jdolecek int
   2919  1.12.12.2  jdolecek sctp_is_there_an_abort_here(struct mbuf *m, int iphlen, int *vtagfill)
   2920  1.12.12.2  jdolecek {
   2921  1.12.12.2  jdolecek 	struct sctp_chunkhdr *ch;
   2922  1.12.12.2  jdolecek 	struct sctp_init_chunk *init_chk, chunk_buf;
   2923  1.12.12.2  jdolecek 	int offset;
   2924  1.12.12.2  jdolecek 	unsigned int chk_length;
   2925  1.12.12.2  jdolecek 
   2926  1.12.12.2  jdolecek 	offset = iphlen + sizeof(struct sctphdr);
   2927  1.12.12.2  jdolecek 	ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset, sizeof(*ch),
   2928  1.12.12.2  jdolecek 	    (u_int8_t *)&chunk_buf);
   2929  1.12.12.2  jdolecek 	while (ch != NULL) {
   2930  1.12.12.2  jdolecek 		chk_length = ntohs(ch->chunk_length);
   2931  1.12.12.2  jdolecek 		if (chk_length < sizeof(*ch)) {
   2932  1.12.12.2  jdolecek 			/* packet is probably corrupt */
   2933  1.12.12.2  jdolecek 			break;
   2934  1.12.12.2  jdolecek 		}
   2935  1.12.12.2  jdolecek 		/* we seem to be ok, is it an abort? */
   2936  1.12.12.2  jdolecek 		if (ch->chunk_type == SCTP_ABORT_ASSOCIATION) {
   2937  1.12.12.2  jdolecek 			/* yep, tell them */
   2938  1.12.12.2  jdolecek 			return (1);
   2939  1.12.12.2  jdolecek 		}
   2940  1.12.12.2  jdolecek 		if (ch->chunk_type == SCTP_INITIATION) {
   2941  1.12.12.2  jdolecek 			/* need to update the Vtag */
   2942  1.12.12.2  jdolecek 			init_chk = (struct sctp_init_chunk *)sctp_m_getptr(m,
   2943  1.12.12.2  jdolecek 			    offset, sizeof(*init_chk), (u_int8_t *)&chunk_buf);
   2944  1.12.12.2  jdolecek 			if (init_chk != NULL) {
   2945  1.12.12.2  jdolecek 				*vtagfill = ntohl(init_chk->init.initiate_tag);
   2946  1.12.12.2  jdolecek 			}
   2947  1.12.12.2  jdolecek 		}
   2948  1.12.12.2  jdolecek 		/* Nope, move to the next chunk */
   2949  1.12.12.2  jdolecek 		offset += SCTP_SIZE32(chk_length);
   2950  1.12.12.2  jdolecek 		ch = (struct sctp_chunkhdr *)sctp_m_getptr(m, offset,
   2951  1.12.12.2  jdolecek 		    sizeof(*ch), (u_int8_t *)&chunk_buf);
   2952  1.12.12.2  jdolecek 	}
   2953  1.12.12.2  jdolecek 	return (0);
   2954  1.12.12.2  jdolecek }
   2955  1.12.12.2  jdolecek 
   2956  1.12.12.2  jdolecek /*
   2957  1.12.12.2  jdolecek  * currently (2/02), ifa_addr embeds scope_id's and don't
   2958  1.12.12.2  jdolecek  * have sin6_scope_id set (i.e. it's 0)
   2959  1.12.12.2  jdolecek  * so, create this function to compare link local scopes
   2960  1.12.12.2  jdolecek  */
   2961  1.12.12.2  jdolecek uint32_t
   2962  1.12.12.2  jdolecek sctp_is_same_scope(const struct sockaddr_in6 *addr1, const struct sockaddr_in6 *addr2)
   2963  1.12.12.2  jdolecek {
   2964  1.12.12.2  jdolecek 	struct sockaddr_in6 a, b;
   2965  1.12.12.2  jdolecek 
   2966  1.12.12.2  jdolecek 	/* save copies */
   2967  1.12.12.2  jdolecek 	a = *addr1;
   2968  1.12.12.2  jdolecek 	b = *addr2;
   2969  1.12.12.2  jdolecek 
   2970  1.12.12.2  jdolecek 	if (a.sin6_scope_id == 0)
   2971  1.12.12.2  jdolecek 		if (sa6_recoverscope(&a)) {
   2972  1.12.12.2  jdolecek 			/* can't get scope, so can't match */
   2973  1.12.12.2  jdolecek 			return (0);
   2974  1.12.12.2  jdolecek 		}
   2975  1.12.12.2  jdolecek 	if (b.sin6_scope_id == 0)
   2976  1.12.12.2  jdolecek 		if (sa6_recoverscope(&b)) {
   2977  1.12.12.2  jdolecek 			/* can't get scope, so can't match */
   2978  1.12.12.2  jdolecek 			return (0);
   2979  1.12.12.2  jdolecek 		}
   2980  1.12.12.2  jdolecek 	if (a.sin6_scope_id != b.sin6_scope_id)
   2981  1.12.12.2  jdolecek 		return (0);
   2982  1.12.12.2  jdolecek 
   2983  1.12.12.2  jdolecek 	return (1);
   2984  1.12.12.2  jdolecek }
   2985  1.12.12.2  jdolecek 
   2986  1.12.12.2  jdolecek /*
   2987  1.12.12.2  jdolecek  * returns a sockaddr_in6 with embedded scope recovered and removed
   2988  1.12.12.2  jdolecek  */
   2989  1.12.12.2  jdolecek const struct sockaddr_in6 *
   2990  1.12.12.2  jdolecek sctp_recover_scope(const struct sockaddr_in6 *addr, struct sockaddr_in6 *store)
   2991  1.12.12.2  jdolecek {
   2992  1.12.12.2  jdolecek 	const struct sockaddr_in6 *newaddr;
   2993  1.12.12.2  jdolecek 
   2994  1.12.12.2  jdolecek 	newaddr = addr;
   2995  1.12.12.2  jdolecek 	/* check and strip embedded scope junk */
   2996  1.12.12.2  jdolecek 	if (addr->sin6_family == AF_INET6) {
   2997  1.12.12.2  jdolecek 		if (IN6_IS_SCOPE_LINKLOCAL(&addr->sin6_addr)) {
   2998  1.12.12.2  jdolecek 			if (addr->sin6_scope_id == 0) {
   2999  1.12.12.2  jdolecek 				*store = *addr;
   3000  1.12.12.2  jdolecek 				if (sa6_recoverscope(store) == 0) {
   3001  1.12.12.2  jdolecek 					/* use the recovered scope */
   3002  1.12.12.2  jdolecek 					newaddr = store;
   3003  1.12.12.2  jdolecek 				}
   3004  1.12.12.2  jdolecek 				/* else, return the original "to" addr */
   3005  1.12.12.2  jdolecek 			}
   3006  1.12.12.2  jdolecek 		}
   3007  1.12.12.2  jdolecek 	}
   3008  1.12.12.2  jdolecek 	return (newaddr);
   3009  1.12.12.2  jdolecek }
   3010  1.12.12.2  jdolecek 
   3011  1.12.12.2  jdolecek /*
   3012  1.12.12.2  jdolecek  * are the two addresses the same?  currently a "scopeless" check
   3013  1.12.12.2  jdolecek  * returns: 1 if same, 0 if not
   3014  1.12.12.2  jdolecek  */
   3015  1.12.12.2  jdolecek int
   3016  1.12.12.2  jdolecek sctp_cmpaddr(const struct sockaddr *sa1, const struct sockaddr *sa2)
   3017  1.12.12.2  jdolecek {
   3018  1.12.12.2  jdolecek 
   3019  1.12.12.2  jdolecek 	/* must be valid */
   3020  1.12.12.2  jdolecek 	if (sa1 == NULL || sa2 == NULL)
   3021  1.12.12.2  jdolecek 		return (0);
   3022  1.12.12.2  jdolecek 
   3023  1.12.12.2  jdolecek 	/* must be the same family */
   3024  1.12.12.2  jdolecek 	if (sa1->sa_family != sa2->sa_family)
   3025  1.12.12.2  jdolecek 		return (0);
   3026  1.12.12.2  jdolecek 
   3027  1.12.12.2  jdolecek 	if (sa1->sa_family == AF_INET6) {
   3028  1.12.12.2  jdolecek 		/* IPv6 addresses */
   3029  1.12.12.2  jdolecek 		const struct sockaddr_in6 *sin6_1, *sin6_2;
   3030  1.12.12.2  jdolecek 
   3031  1.12.12.2  jdolecek 		sin6_1 = (const struct sockaddr_in6 *)sa1;
   3032  1.12.12.2  jdolecek 		sin6_2 = (const struct sockaddr_in6 *)sa2;
   3033  1.12.12.2  jdolecek 		return (SCTP6_ARE_ADDR_EQUAL(&sin6_1->sin6_addr,
   3034  1.12.12.2  jdolecek 		    &sin6_2->sin6_addr));
   3035  1.12.12.2  jdolecek 	} else if (sa1->sa_family == AF_INET) {
   3036  1.12.12.2  jdolecek 		/* IPv4 addresses */
   3037  1.12.12.2  jdolecek 		const struct sockaddr_in *sin_1, *sin_2;
   3038  1.12.12.2  jdolecek 
   3039  1.12.12.2  jdolecek 		sin_1 = (const struct sockaddr_in *)sa1;
   3040  1.12.12.2  jdolecek 		sin_2 = (const struct sockaddr_in *)sa2;
   3041  1.12.12.2  jdolecek 		return (sin_1->sin_addr.s_addr == sin_2->sin_addr.s_addr);
   3042  1.12.12.2  jdolecek 	} else {
   3043  1.12.12.2  jdolecek 		/* we don't do these... */
   3044  1.12.12.2  jdolecek 		return (0);
   3045  1.12.12.2  jdolecek 	}
   3046  1.12.12.2  jdolecek }
   3047  1.12.12.2  jdolecek 
   3048  1.12.12.2  jdolecek void
   3049  1.12.12.2  jdolecek sctp_print_address(const struct sockaddr *sa)
   3050  1.12.12.2  jdolecek {
   3051  1.12.12.2  jdolecek 	char ip6buf[INET6_ADDRSTRLEN];
   3052  1.12.12.2  jdolecek 
   3053  1.12.12.2  jdolecek 	if (sa->sa_family == AF_INET6) {
   3054  1.12.12.2  jdolecek 		const struct sockaddr_in6 *sin6;
   3055  1.12.12.2  jdolecek 		sin6 = (const struct sockaddr_in6 *)sa;
   3056  1.12.12.2  jdolecek 		printf("IPv6 address: %s:%d scope:%u\n",
   3057  1.12.12.2  jdolecek 		    IN6_PRINT(ip6buf, &sin6->sin6_addr), ntohs(sin6->sin6_port),
   3058  1.12.12.2  jdolecek 		    sin6->sin6_scope_id);
   3059  1.12.12.2  jdolecek 	} else if (sa->sa_family == AF_INET) {
   3060  1.12.12.2  jdolecek 		const struct sockaddr_in *sin;
   3061  1.12.12.2  jdolecek 		sin = (const struct sockaddr_in *)sa;
   3062  1.12.12.2  jdolecek 		printf("IPv4 address: %s:%d\n", inet_ntoa(sin->sin_addr),
   3063  1.12.12.2  jdolecek 		    ntohs(sin->sin_port));
   3064  1.12.12.2  jdolecek 	} else {
   3065  1.12.12.2  jdolecek 		printf("?\n");
   3066  1.12.12.2  jdolecek 	}
   3067  1.12.12.2  jdolecek }
   3068  1.12.12.2  jdolecek 
   3069  1.12.12.2  jdolecek void
   3070  1.12.12.2  jdolecek sctp_print_address_pkt(struct ip *iph, struct sctphdr *sh)
   3071  1.12.12.2  jdolecek {
   3072  1.12.12.2  jdolecek 	if (iph->ip_v == IPVERSION) {
   3073  1.12.12.2  jdolecek 		struct sockaddr_in lsa, fsa;
   3074  1.12.12.2  jdolecek 
   3075  1.12.12.2  jdolecek 		memset(&lsa, 0, sizeof(lsa));
   3076  1.12.12.2  jdolecek 		lsa.sin_len = sizeof(lsa);
   3077  1.12.12.2  jdolecek 		lsa.sin_family = AF_INET;
   3078  1.12.12.2  jdolecek 		lsa.sin_addr = iph->ip_src;
   3079  1.12.12.2  jdolecek 		lsa.sin_port = sh->src_port;
   3080  1.12.12.2  jdolecek 		memset(&fsa, 0, sizeof(fsa));
   3081  1.12.12.2  jdolecek 		fsa.sin_len = sizeof(fsa);
   3082  1.12.12.2  jdolecek 		fsa.sin_family = AF_INET;
   3083  1.12.12.2  jdolecek 		fsa.sin_addr = iph->ip_dst;
   3084  1.12.12.2  jdolecek 		fsa.sin_port = sh->dest_port;
   3085  1.12.12.2  jdolecek 		printf("src: ");
   3086  1.12.12.2  jdolecek 		sctp_print_address((struct sockaddr *)&lsa);
   3087  1.12.12.2  jdolecek 		printf("dest: ");
   3088  1.12.12.2  jdolecek 		sctp_print_address((struct sockaddr *)&fsa);
   3089  1.12.12.2  jdolecek 	} else if (iph->ip_v == (IPV6_VERSION >> 4)) {
   3090  1.12.12.2  jdolecek 		struct ip6_hdr *ip6;
   3091  1.12.12.2  jdolecek 		struct sockaddr_in6 lsa6, fsa6;
   3092  1.12.12.2  jdolecek 
   3093  1.12.12.2  jdolecek 		ip6 = (struct ip6_hdr *)iph;
   3094  1.12.12.2  jdolecek 		memset(&lsa6, 0, sizeof(lsa6));
   3095  1.12.12.2  jdolecek 		lsa6.sin6_len = sizeof(lsa6);
   3096  1.12.12.2  jdolecek 		lsa6.sin6_family = AF_INET6;
   3097  1.12.12.2  jdolecek 		lsa6.sin6_addr = ip6->ip6_src;
   3098  1.12.12.2  jdolecek 		lsa6.sin6_port = sh->src_port;
   3099  1.12.12.2  jdolecek 		memset(&fsa6, 0, sizeof(fsa6));
   3100  1.12.12.2  jdolecek 		fsa6.sin6_len = sizeof(fsa6);
   3101  1.12.12.2  jdolecek 		fsa6.sin6_family = AF_INET6;
   3102  1.12.12.2  jdolecek 		fsa6.sin6_addr = ip6->ip6_dst;
   3103  1.12.12.2  jdolecek 		fsa6.sin6_port = sh->dest_port;
   3104  1.12.12.2  jdolecek 		printf("src: ");
   3105  1.12.12.2  jdolecek 		sctp_print_address((struct sockaddr *)&lsa6);
   3106  1.12.12.2  jdolecek 		printf("dest: ");
   3107  1.12.12.2  jdolecek 		sctp_print_address((struct sockaddr *)&fsa6);
   3108  1.12.12.2  jdolecek 	}
   3109  1.12.12.2  jdolecek }
   3110  1.12.12.2  jdolecek 
   3111  1.12.12.2  jdolecek #if defined(__FreeBSD__) || defined(__APPLE__)
   3112  1.12.12.2  jdolecek 
   3113  1.12.12.2  jdolecek /* cloned from uipc_socket.c */
   3114  1.12.12.2  jdolecek 
   3115  1.12.12.2  jdolecek #define SCTP_SBLINKRECORD(sb, m0) do {					\
   3116  1.12.12.2  jdolecek 	if ((sb)->sb_lastrecord != NULL)				\
   3117  1.12.12.2  jdolecek 		(sb)->sb_lastrecord->m_nextpkt = (m0);			\
   3118  1.12.12.2  jdolecek 	else								\
   3119  1.12.12.2  jdolecek 		(sb)->sb_mb = (m0);					\
   3120  1.12.12.2  jdolecek 	(sb)->sb_lastrecord = (m0);					\
   3121  1.12.12.2  jdolecek } while (/*CONSTCOND*/0)
   3122  1.12.12.2  jdolecek #endif
   3123  1.12.12.2  jdolecek 
   3124  1.12.12.2  jdolecek 
   3125  1.12.12.2  jdolecek int
   3126  1.12.12.2  jdolecek sbappendaddr_nocheck(struct sockbuf *sb, const struct sockaddr *asa,
   3127  1.12.12.2  jdolecek 	struct mbuf *m0, struct mbuf *control,
   3128  1.12.12.2  jdolecek 	u_int32_t tag, struct sctp_inpcb *inp)
   3129  1.12.12.2  jdolecek {
   3130  1.12.12.2  jdolecek #ifdef __NetBSD__
   3131  1.12.12.2  jdolecek 	struct mbuf *m, *n;
   3132  1.12.12.2  jdolecek 
   3133  1.12.12.2  jdolecek 	if (m0 && (m0->m_flags & M_PKTHDR) == 0)
   3134  1.12.12.2  jdolecek 		panic("sbappendaddr_nocheck");
   3135  1.12.12.2  jdolecek 
   3136  1.12.12.2  jdolecek 	m0->m_pkthdr.csum_data = (int)tag;
   3137  1.12.12.2  jdolecek 
   3138  1.12.12.2  jdolecek 	for (n = control; n; n = n->m_next) {
   3139  1.12.12.2  jdolecek 		if (n->m_next == 0)	/* keep pointer to last control buf */
   3140  1.12.12.2  jdolecek 			break;
   3141  1.12.12.2  jdolecek 	}
   3142  1.12.12.2  jdolecek 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
   3143  1.12.12.2  jdolecek 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
   3144  1.12.12.2  jdolecek 		MGETHDR(m, M_DONTWAIT, MT_SONAME);
   3145  1.12.12.2  jdolecek 		if (m == 0)
   3146  1.12.12.2  jdolecek 			return (0);
   3147  1.12.12.2  jdolecek 
   3148  1.12.12.2  jdolecek 		m->m_len = asa->sa_len;
   3149  1.12.12.2  jdolecek 		memcpy(mtod(m, void *), (const void *)asa, asa->sa_len);
   3150  1.12.12.2  jdolecek 	} else {
   3151  1.12.12.2  jdolecek 		m = NULL;
   3152  1.12.12.2  jdolecek 	}
   3153  1.12.12.2  jdolecek 	if (n) {
   3154  1.12.12.2  jdolecek 		n->m_next = m0;		/* concatenate data to control */
   3155  1.12.12.2  jdolecek 	}else {
   3156  1.12.12.2  jdolecek 		control = m0;
   3157  1.12.12.2  jdolecek 	}
   3158  1.12.12.2  jdolecek 	if (m)
   3159  1.12.12.2  jdolecek 		m->m_next = control;
   3160  1.12.12.2  jdolecek 	else
   3161  1.12.12.2  jdolecek 		m = control;
   3162  1.12.12.2  jdolecek 	m->m_pkthdr.csum_data = tag;
   3163  1.12.12.2  jdolecek 
   3164  1.12.12.2  jdolecek 	for (n = m; n; n = n->m_next)
   3165  1.12.12.2  jdolecek 		sballoc(sb, n);
   3166  1.12.12.2  jdolecek 	if ((n = sb->sb_mb) != NULL) {
   3167  1.12.12.2  jdolecek 		if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
   3168  1.12.12.2  jdolecek 			inp->sb_last_mpkt = NULL;
   3169  1.12.12.2  jdolecek 		}
   3170  1.12.12.2  jdolecek 		if (inp->sb_last_mpkt)
   3171  1.12.12.2  jdolecek 			inp->sb_last_mpkt->m_nextpkt = m;
   3172  1.12.12.2  jdolecek  		else {
   3173  1.12.12.2  jdolecek 			while (n->m_nextpkt) {
   3174  1.12.12.2  jdolecek 				n = n->m_nextpkt;
   3175  1.12.12.2  jdolecek 			}
   3176  1.12.12.2  jdolecek 			n->m_nextpkt = m;
   3177  1.12.12.2  jdolecek 		}
   3178  1.12.12.2  jdolecek 		inp->sb_last_mpkt = m;
   3179  1.12.12.2  jdolecek 	} else {
   3180  1.12.12.2  jdolecek 		inp->sb_last_mpkt = sb->sb_mb = m;
   3181  1.12.12.2  jdolecek 		inp->sctp_vtag_first = tag;
   3182  1.12.12.2  jdolecek 	}
   3183  1.12.12.2  jdolecek 	return (1);
   3184  1.12.12.2  jdolecek #endif
   3185  1.12.12.2  jdolecek #if defined(__FreeBSD__) || defined(__APPLE__)
   3186  1.12.12.2  jdolecek 	struct mbuf *m, *n, *nlast;
   3187  1.12.12.2  jdolecek 	int cnt=0;
   3188  1.12.12.2  jdolecek 
   3189  1.12.12.2  jdolecek 	if (m0 && (m0->m_flags & M_PKTHDR) == 0)
   3190  1.12.12.2  jdolecek 		panic("sbappendaddr_nocheck");
   3191  1.12.12.2  jdolecek 
   3192  1.12.12.2  jdolecek 	for (n = control; n; n = n->m_next) {
   3193  1.12.12.2  jdolecek 		if (n->m_next == 0)	/* get pointer to last control buf */
   3194  1.12.12.2  jdolecek 			break;
   3195  1.12.12.2  jdolecek 	}
   3196  1.12.12.2  jdolecek 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
   3197  1.12.12.2  jdolecek 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
   3198  1.12.12.2  jdolecek 		if (asa->sa_len > MHLEN)
   3199  1.12.12.2  jdolecek 			return (0);
   3200  1.12.12.2  jdolecek  try_again:
   3201  1.12.12.2  jdolecek 		MGETHDR(m, M_DONTWAIT, MT_SONAME);
   3202  1.12.12.2  jdolecek 		if (m == 0)
   3203  1.12.12.2  jdolecek 			return (0);
   3204  1.12.12.2  jdolecek 		m->m_len = 0;
   3205  1.12.12.2  jdolecek 		/* safety */
   3206  1.12.12.2  jdolecek 		if (m == m0) {
   3207  1.12.12.2  jdolecek 			printf("Duplicate mbuf allocated %p in and mget returned %p?\n",
   3208  1.12.12.2  jdolecek 			       m0, m);
   3209  1.12.12.2  jdolecek 			if (cnt) {
   3210  1.12.12.2  jdolecek 				panic("more than once");
   3211  1.12.12.2  jdolecek 			}
   3212  1.12.12.2  jdolecek 			cnt++;
   3213  1.12.12.2  jdolecek 			goto try_again;
   3214  1.12.12.2  jdolecek 		}
   3215  1.12.12.2  jdolecek 		m->m_len = asa->sa_len;
   3216  1.12.12.2  jdolecek 		bcopy((void *)asa, mtod(m, void *), asa->sa_len);
   3217  1.12.12.2  jdolecek 	}
   3218  1.12.12.2  jdolecek 	else {
   3219  1.12.12.2  jdolecek 		m = NULL;
   3220  1.12.12.2  jdolecek 	}
   3221  1.12.12.2  jdolecek 	if (n)
   3222  1.12.12.2  jdolecek 		n->m_next = m0;		/* concatenate data to control */
   3223  1.12.12.2  jdolecek 	else
   3224  1.12.12.2  jdolecek 		control = m0;
   3225  1.12.12.2  jdolecek 	if (m)
   3226  1.12.12.2  jdolecek 		m->m_next = control;
   3227  1.12.12.2  jdolecek 	else
   3228  1.12.12.2  jdolecek 		m = control;
   3229  1.12.12.2  jdolecek 	m->m_pkthdr.csum_data = (int)tag;
   3230  1.12.12.2  jdolecek 
   3231  1.12.12.2  jdolecek 	for (n = m; n; n = n->m_next)
   3232  1.12.12.2  jdolecek 		sballoc(sb, n);
   3233  1.12.12.2  jdolecek 	nlast = n;
   3234  1.12.12.2  jdolecek 	if (sb->sb_mb == NULL) {
   3235  1.12.12.2  jdolecek 		inp->sctp_vtag_first = tag;
   3236  1.12.12.2  jdolecek 	}
   3237  1.12.12.2  jdolecek 
   3238  1.12.12.2  jdolecek #ifdef __FREEBSD__
   3239  1.12.12.2  jdolecek 	if (sb->sb_mb == NULL)
   3240  1.12.12.2  jdolecek 		inp->sctp_vtag_first = tag;
   3241  1.12.12.2  jdolecek 	SCTP_SBLINKRECORD(sb, m);
   3242  1.12.12.2  jdolecek 	sb->sb_mbtail = nlast;
   3243  1.12.12.2  jdolecek #else
   3244  1.12.12.2  jdolecek 	if ((n = sb->sb_mb) != NULL) {
   3245  1.12.12.2  jdolecek 		if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
   3246  1.12.12.2  jdolecek 			inp->sb_last_mpkt = NULL;
   3247  1.12.12.2  jdolecek 		}
   3248  1.12.12.2  jdolecek 		if (inp->sb_last_mpkt)
   3249  1.12.12.2  jdolecek 			inp->sb_last_mpkt->m_nextpkt = m;
   3250  1.12.12.2  jdolecek  		else {
   3251  1.12.12.2  jdolecek 			while (n->m_nextpkt) {
   3252  1.12.12.2  jdolecek 				n = n->m_nextpkt;
   3253  1.12.12.2  jdolecek 			}
   3254  1.12.12.2  jdolecek 			n->m_nextpkt = m;
   3255  1.12.12.2  jdolecek 		}
   3256  1.12.12.2  jdolecek 		inp->sb_last_mpkt = m;
   3257  1.12.12.2  jdolecek 	} else {
   3258  1.12.12.2  jdolecek 		inp->sb_last_mpkt = sb->sb_mb = m;
   3259  1.12.12.2  jdolecek 		inp->sctp_vtag_first = tag;
   3260  1.12.12.2  jdolecek 	}
   3261  1.12.12.2  jdolecek #endif
   3262  1.12.12.2  jdolecek 	return (1);
   3263  1.12.12.2  jdolecek #endif
   3264  1.12.12.2  jdolecek #ifdef __OpenBSD__
   3265  1.12.12.2  jdolecek 	struct mbuf *m, *n;
   3266  1.12.12.2  jdolecek 
   3267  1.12.12.2  jdolecek 	if (m0 && (m0->m_flags & M_PKTHDR) == 0)
   3268  1.12.12.2  jdolecek 		panic("sbappendaddr_nocheck");
   3269  1.12.12.2  jdolecek 	m0->m_pkthdr.csum = (int)tag;
   3270  1.12.12.2  jdolecek 	for (n = control; n; n = n->m_next) {
   3271  1.12.12.2  jdolecek 		if (n->m_next == 0)	/* keep pointer to last control buf */
   3272  1.12.12.2  jdolecek 			break;
   3273  1.12.12.2  jdolecek 	}
   3274  1.12.12.2  jdolecek 	if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) ||
   3275  1.12.12.2  jdolecek 	    ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)== 0)) {
   3276  1.12.12.2  jdolecek 		if (asa->sa_len > MHLEN)
   3277  1.12.12.2  jdolecek 			return (0);
   3278  1.12.12.2  jdolecek 		MGETHDR(m, M_DONTWAIT, MT_SONAME);
   3279  1.12.12.2  jdolecek 		if (m == 0)
   3280  1.12.12.2  jdolecek 			return (0);
   3281  1.12.12.2  jdolecek 		m->m_len = asa->sa_len;
   3282  1.12.12.2  jdolecek 		bcopy((void *)asa, mtod(m, void *), asa->sa_len);
   3283  1.12.12.2  jdolecek 	} else {
   3284  1.12.12.2  jdolecek 		m = NULL;
   3285  1.12.12.2  jdolecek 	}
   3286  1.12.12.2  jdolecek 	if (n)
   3287  1.12.12.2  jdolecek 		n->m_next = m0;		/* concatenate data to control */
   3288  1.12.12.2  jdolecek 	else
   3289  1.12.12.2  jdolecek 		control = m0;
   3290  1.12.12.2  jdolecek 
   3291  1.12.12.2  jdolecek 	m->m_pkthdr.csum = (int)tag;
   3292  1.12.12.2  jdolecek 	m->m_next = control;
   3293  1.12.12.2  jdolecek 	for (n = m; n; n = n->m_next)
   3294  1.12.12.2  jdolecek 		sballoc(sb, n);
   3295  1.12.12.2  jdolecek 	if ((n = sb->sb_mb) != NULL) {
   3296  1.12.12.2  jdolecek 		if ((n->m_nextpkt != inp->sb_last_mpkt) && (n->m_nextpkt == NULL)) {
   3297  1.12.12.2  jdolecek 			inp->sb_last_mpkt = NULL;
   3298  1.12.12.2  jdolecek 		}
   3299  1.12.12.2  jdolecek 		if (inp->sb_last_mpkt)
   3300  1.12.12.2  jdolecek 			inp->sb_last_mpkt->m_nextpkt = m;
   3301  1.12.12.2  jdolecek  		else {
   3302  1.12.12.2  jdolecek 			while (n->m_nextpkt) {
   3303  1.12.12.2  jdolecek 				n = n->m_nextpkt;
   3304  1.12.12.2  jdolecek 			}
   3305  1.12.12.2  jdolecek 			n->m_nextpkt = m;
   3306  1.12.12.2  jdolecek 		}
   3307  1.12.12.2  jdolecek 		inp->sb_last_mpkt = m;
   3308  1.12.12.2  jdolecek 	} else {
   3309  1.12.12.2  jdolecek 		inp->sb_last_mpkt = sb->sb_mb = m;
   3310  1.12.12.2  jdolecek 		inp->sctp_vtag_first = tag;
   3311  1.12.12.2  jdolecek 	}
   3312  1.12.12.2  jdolecek 	return (1);
   3313  1.12.12.2  jdolecek #endif
   3314  1.12.12.2  jdolecek }
   3315  1.12.12.2  jdolecek 
   3316  1.12.12.2  jdolecek /*************HOLD THIS COMMENT FOR PATCH FILE OF
   3317  1.12.12.2  jdolecek  *************ALTERNATE ROUTING CODE
   3318  1.12.12.2  jdolecek  */
   3319  1.12.12.2  jdolecek 
   3320  1.12.12.2  jdolecek /*************HOLD THIS COMMENT FOR END OF PATCH FILE OF
   3321  1.12.12.2  jdolecek  *************ALTERNATE ROUTING CODE
   3322  1.12.12.2  jdolecek  */
   3323  1.12.12.2  jdolecek 
   3324  1.12.12.2  jdolecek struct mbuf *
   3325  1.12.12.2  jdolecek sctp_generate_invmanparam(int err)
   3326  1.12.12.2  jdolecek {
   3327  1.12.12.2  jdolecek 	/* Return a MBUF with a invalid mandatory parameter */
   3328  1.12.12.2  jdolecek 	struct mbuf *m;
   3329  1.12.12.2  jdolecek 
   3330  1.12.12.2  jdolecek 	MGET(m, M_DONTWAIT, MT_DATA);
   3331  1.12.12.2  jdolecek 	if (m) {
   3332  1.12.12.2  jdolecek 		struct sctp_paramhdr *ph;
   3333  1.12.12.2  jdolecek 		m->m_len = sizeof(struct sctp_paramhdr);
   3334  1.12.12.2  jdolecek 		ph = mtod(m, struct sctp_paramhdr *);
   3335  1.12.12.2  jdolecek 		ph->param_length = htons(sizeof(struct sctp_paramhdr));
   3336  1.12.12.2  jdolecek 		ph->param_type = htons(err);
   3337  1.12.12.2  jdolecek 	}
   3338  1.12.12.2  jdolecek 	return (m);
   3339  1.12.12.2  jdolecek }
   3340  1.12.12.2  jdolecek 
   3341  1.12.12.2  jdolecek static int
   3342  1.12.12.2  jdolecek sctp_should_be_moved(struct mbuf *this, struct sctp_association *asoc)
   3343  1.12.12.2  jdolecek {
   3344  1.12.12.2  jdolecek 	struct mbuf *m;
   3345  1.12.12.2  jdolecek 	/*
   3346  1.12.12.2  jdolecek 	 * given a mbuf chain, look through it finding
   3347  1.12.12.2  jdolecek 	 * the M_PKTHDR and return 1 if it belongs to
   3348  1.12.12.2  jdolecek 	 * the association given. We tell this by
   3349  1.12.12.2  jdolecek 	 * a kludge where we stuff the my_vtag of the asoc
   3350  1.12.12.2  jdolecek 	 * into the m->m_pkthdr.csum_data/csum field.
   3351  1.12.12.2  jdolecek 	 */
   3352  1.12.12.2  jdolecek 	m = this;
   3353  1.12.12.2  jdolecek 	while (m) {
   3354  1.12.12.2  jdolecek 		if (m->m_flags & M_PKTHDR) {
   3355  1.12.12.2  jdolecek 			/* check it */
   3356  1.12.12.2  jdolecek #if defined(__OpenBSD__)
   3357  1.12.12.2  jdolecek 			if ((u_int32_t)m->m_pkthdr.csum == asoc->my_vtag)
   3358  1.12.12.2  jdolecek #else
   3359  1.12.12.2  jdolecek 			if ((u_int32_t)m->m_pkthdr.csum_data == asoc->my_vtag)
   3360  1.12.12.2  jdolecek #endif
   3361  1.12.12.2  jdolecek 			{
   3362  1.12.12.2  jdolecek 				/* Yep */
   3363  1.12.12.2  jdolecek 				return (1);
   3364  1.12.12.2  jdolecek 			}
   3365  1.12.12.2  jdolecek 		}
   3366  1.12.12.2  jdolecek 		m = m->m_next;
   3367  1.12.12.2  jdolecek 	}
   3368  1.12.12.2  jdolecek 	return (0);
   3369  1.12.12.2  jdolecek }
   3370  1.12.12.2  jdolecek 
   3371  1.12.12.2  jdolecek u_int32_t
   3372  1.12.12.2  jdolecek sctp_get_first_vtag_from_sb(struct socket *so)
   3373  1.12.12.2  jdolecek {
   3374  1.12.12.2  jdolecek 	struct mbuf *this, *at;
   3375  1.12.12.2  jdolecek 	u_int32_t retval;
   3376  1.12.12.2  jdolecek 
   3377  1.12.12.2  jdolecek 	retval = 0;
   3378  1.12.12.2  jdolecek 	if (so->so_rcv.sb_mb) {
   3379  1.12.12.2  jdolecek 		/* grubbing time */
   3380  1.12.12.2  jdolecek 		this = so->so_rcv.sb_mb;
   3381  1.12.12.2  jdolecek 		while (this) {
   3382  1.12.12.2  jdolecek 			at = this;
   3383  1.12.12.2  jdolecek 			/* get to the m_pkthdr */
   3384  1.12.12.2  jdolecek 			while (at) {
   3385  1.12.12.2  jdolecek 				if (at->m_flags & M_PKTHDR)
   3386  1.12.12.2  jdolecek 					break;
   3387  1.12.12.2  jdolecek 				else {
   3388  1.12.12.2  jdolecek 					at = at->m_next;
   3389  1.12.12.2  jdolecek 				}
   3390  1.12.12.2  jdolecek 			}
   3391  1.12.12.2  jdolecek 			/* now do we have a m_pkthdr */
   3392  1.12.12.2  jdolecek 			if (at && (at->m_flags & M_PKTHDR)) {
   3393  1.12.12.2  jdolecek 				/* check it */
   3394  1.12.12.2  jdolecek #if defined(__OpenBSD__)
   3395  1.12.12.2  jdolecek 				if ((u_int32_t)at->m_pkthdr.csum != 0)
   3396  1.12.12.2  jdolecek #else
   3397  1.12.12.2  jdolecek 				if ((u_int32_t)at->m_pkthdr.csum_data != 0)
   3398  1.12.12.2  jdolecek #endif
   3399  1.12.12.2  jdolecek 				{
   3400  1.12.12.2  jdolecek 					/* its the one */
   3401  1.12.12.2  jdolecek #if defined(__OpenBSD__)
   3402  1.12.12.2  jdolecek 					retval = (u_int32_t)at->m_pkthdr.csum;
   3403  1.12.12.2  jdolecek #else
   3404  1.12.12.2  jdolecek 					retval =
   3405  1.12.12.2  jdolecek 					    (u_int32_t)at->m_pkthdr.csum_data;
   3406  1.12.12.2  jdolecek #endif
   3407  1.12.12.2  jdolecek 					break;
   3408  1.12.12.2  jdolecek 				}
   3409  1.12.12.2  jdolecek 			}
   3410  1.12.12.2  jdolecek 			this = this->m_nextpkt;
   3411  1.12.12.2  jdolecek 		}
   3412  1.12.12.2  jdolecek 
   3413  1.12.12.2  jdolecek 	}
   3414  1.12.12.2  jdolecek 	return (retval);
   3415  1.12.12.2  jdolecek 
   3416  1.12.12.2  jdolecek }
   3417  1.12.12.2  jdolecek void
   3418  1.12.12.2  jdolecek sctp_grub_through_socket_buffer(struct sctp_inpcb *inp, struct socket *old,
   3419  1.12.12.2  jdolecek     struct socket *new, struct sctp_tcb *stcb)
   3420  1.12.12.2  jdolecek {
   3421  1.12.12.2  jdolecek 	struct mbuf **put, **take, *next, *this;
   3422  1.12.12.2  jdolecek 	struct sockbuf *old_sb, *new_sb;
   3423  1.12.12.2  jdolecek 	struct sctp_association *asoc;
   3424  1.12.12.2  jdolecek 	int moved_top = 0;
   3425  1.12.12.2  jdolecek 
   3426  1.12.12.2  jdolecek 	asoc = &stcb->asoc;
   3427  1.12.12.2  jdolecek 	old_sb = &old->so_rcv;
   3428  1.12.12.2  jdolecek 	new_sb = &new->so_rcv;
   3429  1.12.12.2  jdolecek 	if (old_sb->sb_mb == NULL) {
   3430  1.12.12.2  jdolecek 		/* Nothing to move */
   3431  1.12.12.2  jdolecek 		return;
   3432  1.12.12.2  jdolecek 	}
   3433  1.12.12.2  jdolecek 
   3434  1.12.12.2  jdolecek 	if (inp->sctp_vtag_first == asoc->my_vtag) {
   3435  1.12.12.2  jdolecek 		/* First one must be moved */
   3436  1.12.12.2  jdolecek 		struct mbuf *mm;
   3437  1.12.12.2  jdolecek 		for (mm = old_sb->sb_mb; mm; mm = mm->m_next) {
   3438  1.12.12.2  jdolecek 			/*
   3439  1.12.12.2  jdolecek 			 * Go down the chain and fix
   3440  1.12.12.2  jdolecek 			 * the space allocation of the
   3441  1.12.12.2  jdolecek 			 * two sockets.
   3442  1.12.12.2  jdolecek 			 */
   3443  1.12.12.2  jdolecek 			sbfree(old_sb, mm);
   3444  1.12.12.2  jdolecek 			sballoc(new_sb, mm);
   3445  1.12.12.2  jdolecek 		}
   3446  1.12.12.2  jdolecek 		new_sb->sb_mb = old_sb->sb_mb;
   3447  1.12.12.2  jdolecek 		old_sb->sb_mb = new_sb->sb_mb->m_nextpkt;
   3448  1.12.12.2  jdolecek 		new_sb->sb_mb->m_nextpkt = NULL;
   3449  1.12.12.2  jdolecek 		put = &new_sb->sb_mb->m_nextpkt;
   3450  1.12.12.2  jdolecek 		moved_top = 1;
   3451  1.12.12.2  jdolecek 	} else {
   3452  1.12.12.2  jdolecek 		put = &new_sb->sb_mb;
   3453  1.12.12.2  jdolecek 	}
   3454  1.12.12.2  jdolecek 
   3455  1.12.12.2  jdolecek 	take = &old_sb->sb_mb;
   3456  1.12.12.2  jdolecek 	next = old_sb->sb_mb;
   3457  1.12.12.2  jdolecek 	while (next) {
   3458  1.12.12.2  jdolecek 		this = next;
   3459  1.12.12.2  jdolecek 		/* postion for next one */
   3460  1.12.12.2  jdolecek 		next = this->m_nextpkt;
   3461  1.12.12.2  jdolecek 		/* check the tag of this packet */
   3462  1.12.12.2  jdolecek 		if (sctp_should_be_moved(this, asoc)) {
   3463  1.12.12.2  jdolecek 			/* yes this needs to be moved */
   3464  1.12.12.2  jdolecek 			struct mbuf *mm;
   3465  1.12.12.2  jdolecek 			*take = this->m_nextpkt;
   3466  1.12.12.2  jdolecek 			this->m_nextpkt = NULL;
   3467  1.12.12.2  jdolecek 			*put = this;
   3468  1.12.12.2  jdolecek 			for (mm = this; mm; mm = mm->m_next) {
   3469  1.12.12.2  jdolecek 				/*
   3470  1.12.12.2  jdolecek 				 * Go down the chain and fix
   3471  1.12.12.2  jdolecek 				 * the space allocation of the
   3472  1.12.12.2  jdolecek 				 * two sockets.
   3473  1.12.12.2  jdolecek 				 */
   3474  1.12.12.2  jdolecek 				sbfree(old_sb, mm);
   3475  1.12.12.2  jdolecek 				sballoc(new_sb, mm);
   3476  1.12.12.2  jdolecek 			}
   3477  1.12.12.2  jdolecek 			put = &this->m_nextpkt;
   3478  1.12.12.2  jdolecek 
   3479  1.12.12.2  jdolecek 		} else {
   3480  1.12.12.2  jdolecek 			/* no advance our take point. */
   3481  1.12.12.2  jdolecek 			take = &this->m_nextpkt;
   3482  1.12.12.2  jdolecek 		}
   3483  1.12.12.2  jdolecek 	}
   3484  1.12.12.2  jdolecek 	if (moved_top) {
   3485  1.12.12.2  jdolecek 		/*
   3486  1.12.12.2  jdolecek 		 * Ok so now we must re-postion vtag_first to
   3487  1.12.12.2  jdolecek 		 * match the new first one since we moved the
   3488  1.12.12.2  jdolecek 		 * mbuf at the top.
   3489  1.12.12.2  jdolecek 		 */
   3490  1.12.12.2  jdolecek 		inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(old);
   3491  1.12.12.2  jdolecek 	}
   3492  1.12.12.2  jdolecek }
   3493  1.12.12.2  jdolecek 
   3494  1.12.12.2  jdolecek void
   3495  1.12.12.2  jdolecek sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
   3496  1.12.12.2  jdolecek     struct sctp_tmit_chunk *tp1)
   3497  1.12.12.2  jdolecek {
   3498  1.12.12.2  jdolecek 	if (tp1->data == NULL) {
   3499  1.12.12.2  jdolecek 		return;
   3500  1.12.12.2  jdolecek 	}
   3501  1.12.12.2  jdolecek #ifdef SCTP_MBCNT_LOGGING
   3502  1.12.12.2  jdolecek 	sctp_log_mbcnt(SCTP_LOG_MBCNT_DECREASE,
   3503  1.12.12.2  jdolecek 		       asoc->total_output_queue_size,
   3504  1.12.12.2  jdolecek 		       tp1->book_size,
   3505  1.12.12.2  jdolecek 		       asoc->total_output_mbuf_queue_size,
   3506  1.12.12.2  jdolecek 		       tp1->mbcnt);
   3507  1.12.12.2  jdolecek #endif
   3508  1.12.12.2  jdolecek 	if (asoc->total_output_queue_size >= tp1->book_size) {
   3509  1.12.12.2  jdolecek 		asoc->total_output_queue_size -= tp1->book_size;
   3510  1.12.12.2  jdolecek 	} else {
   3511  1.12.12.2  jdolecek 		asoc->total_output_queue_size = 0;
   3512  1.12.12.2  jdolecek 	}
   3513  1.12.12.2  jdolecek 
   3514  1.12.12.2  jdolecek 	/* Now free the mbuf */
   3515  1.12.12.2  jdolecek 	if (asoc->total_output_mbuf_queue_size >= tp1->mbcnt) {
   3516  1.12.12.2  jdolecek 		asoc->total_output_mbuf_queue_size -= tp1->mbcnt;
   3517  1.12.12.2  jdolecek 	} else {
   3518  1.12.12.2  jdolecek 		asoc->total_output_mbuf_queue_size = 0;
   3519  1.12.12.2  jdolecek 	}
   3520  1.12.12.2  jdolecek 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
   3521  1.12.12.2  jdolecek 	    (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
   3522  1.12.12.2  jdolecek 		if (stcb->sctp_socket->so_snd.sb_cc >= tp1->book_size) {
   3523  1.12.12.2  jdolecek 			stcb->sctp_socket->so_snd.sb_cc -= tp1->book_size;
   3524  1.12.12.2  jdolecek 		} else {
   3525  1.12.12.2  jdolecek 			stcb->sctp_socket->so_snd.sb_cc = 0;
   3526  1.12.12.2  jdolecek 
   3527  1.12.12.2  jdolecek 		}
   3528  1.12.12.2  jdolecek 		if (stcb->sctp_socket->so_snd.sb_mbcnt >= tp1->mbcnt) {
   3529  1.12.12.2  jdolecek 			stcb->sctp_socket->so_snd.sb_mbcnt -= tp1->mbcnt;
   3530  1.12.12.2  jdolecek 		} else {
   3531  1.12.12.2  jdolecek 			stcb->sctp_socket->so_snd.sb_mbcnt = 0;
   3532  1.12.12.2  jdolecek 		}
   3533  1.12.12.2  jdolecek 	}
   3534  1.12.12.2  jdolecek }
   3535  1.12.12.2  jdolecek 
   3536  1.12.12.2  jdolecek int
   3537  1.12.12.2  jdolecek sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
   3538  1.12.12.2  jdolecek     int reason, struct sctpchunk_listhead *queue)
   3539  1.12.12.2  jdolecek {
   3540  1.12.12.2  jdolecek 	int ret_sz = 0;
   3541  1.12.12.2  jdolecek 	int notdone;
   3542  1.12.12.2  jdolecek 	uint8_t foundeom = 0;
   3543  1.12.12.2  jdolecek 
   3544  1.12.12.2  jdolecek 	do {
   3545  1.12.12.2  jdolecek 		ret_sz += tp1->book_size;
   3546  1.12.12.2  jdolecek 		tp1->sent = SCTP_FORWARD_TSN_SKIP;
   3547  1.12.12.2  jdolecek 		if (tp1->data) {
   3548  1.12.12.2  jdolecek 			sctp_free_bufspace(stcb, &stcb->asoc, tp1);
   3549  1.12.12.2  jdolecek 			sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1);
   3550  1.12.12.2  jdolecek 			sctp_m_freem(tp1->data);
   3551  1.12.12.2  jdolecek 			tp1->data = NULL;
   3552  1.12.12.2  jdolecek 			sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
   3553  1.12.12.2  jdolecek 		}
   3554  1.12.12.2  jdolecek 		if (tp1->flags & SCTP_PR_SCTP_BUFFER) {
   3555  1.12.12.2  jdolecek 			stcb->asoc.sent_queue_cnt_removeable--;
   3556  1.12.12.2  jdolecek 		}
   3557  1.12.12.2  jdolecek 		if (queue == &stcb->asoc.send_queue) {
   3558  1.12.12.2  jdolecek 			TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
   3559  1.12.12.2  jdolecek 			/* on to the sent queue */
   3560  1.12.12.2  jdolecek 			TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
   3561  1.12.12.2  jdolecek 			    sctp_next);
   3562  1.12.12.2  jdolecek 			stcb->asoc.sent_queue_cnt++;
   3563  1.12.12.2  jdolecek 		}
   3564  1.12.12.2  jdolecek 		if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
   3565  1.12.12.2  jdolecek 		    SCTP_DATA_NOT_FRAG) {
   3566  1.12.12.2  jdolecek 			/* not frag'ed we ae done   */
   3567  1.12.12.2  jdolecek 			notdone = 0;
   3568  1.12.12.2  jdolecek 			foundeom = 1;
   3569  1.12.12.2  jdolecek 		} else if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
   3570  1.12.12.2  jdolecek 			/* end of frag, we are done */
   3571  1.12.12.2  jdolecek 			notdone = 0;
   3572  1.12.12.2  jdolecek 			foundeom = 1;
   3573  1.12.12.2  jdolecek 		} else {
   3574  1.12.12.2  jdolecek 			/* Its a begin or middle piece, we must mark all of it */
   3575  1.12.12.2  jdolecek 			notdone = 1;
   3576  1.12.12.2  jdolecek 			tp1 = TAILQ_NEXT(tp1, sctp_next);
   3577  1.12.12.2  jdolecek 		}
   3578  1.12.12.2  jdolecek 	} while (tp1 && notdone);
   3579  1.12.12.2  jdolecek 	if ((foundeom == 0) && (queue == &stcb->asoc.sent_queue)) {
   3580  1.12.12.2  jdolecek 		/*
   3581  1.12.12.2  jdolecek 		 * The multi-part message was scattered
   3582  1.12.12.2  jdolecek 		 * across the send and sent queue.
   3583  1.12.12.2  jdolecek 		 */
   3584  1.12.12.2  jdolecek 		tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
   3585  1.12.12.2  jdolecek 		/*
   3586  1.12.12.2  jdolecek 		 * recurse throught the send_queue too, starting at the
   3587  1.12.12.2  jdolecek 		 * beginning.
   3588  1.12.12.2  jdolecek 		 */
   3589  1.12.12.2  jdolecek 		if (tp1) {
   3590  1.12.12.2  jdolecek 			ret_sz += sctp_release_pr_sctp_chunk(stcb, tp1, reason,
   3591  1.12.12.2  jdolecek 			    &stcb->asoc.send_queue);
   3592  1.12.12.2  jdolecek 		} else {
   3593  1.12.12.2  jdolecek 			printf("hmm, nothing on the send queue and no EOM?\n");
   3594  1.12.12.2  jdolecek 		}
   3595  1.12.12.2  jdolecek 	}
   3596  1.12.12.2  jdolecek 	return (ret_sz);
   3597  1.12.12.2  jdolecek }
   3598  1.12.12.2  jdolecek 
   3599  1.12.12.2  jdolecek /*
   3600  1.12.12.2  jdolecek  * checks to see if the given address, sa, is one that is currently
   3601  1.12.12.2  jdolecek  * known by the kernel
   3602  1.12.12.2  jdolecek  * note: can't distinguish the same address on multiple interfaces and
   3603  1.12.12.2  jdolecek  *       doesn't handle multiple addresses with different zone/scope id's
   3604  1.12.12.2  jdolecek  * note: ifa_ifwithaddr() compares the entire sockaddr struct
   3605  1.12.12.2  jdolecek  */
   3606  1.12.12.2  jdolecek struct ifaddr *
   3607  1.12.12.2  jdolecek sctp_find_ifa_by_addr(struct sockaddr *sa)
   3608  1.12.12.2  jdolecek {
   3609  1.12.12.2  jdolecek 	struct ifnet *ifn;
   3610  1.12.12.2  jdolecek 	struct ifaddr *ifa;
   3611  1.12.12.2  jdolecek 	int s;
   3612  1.12.12.2  jdolecek 
   3613  1.12.12.2  jdolecek 	/* go through all our known interfaces */
   3614  1.12.12.2  jdolecek 	s = pserialize_read_enter();
   3615  1.12.12.2  jdolecek 	IFNET_READER_FOREACH(ifn) {
   3616  1.12.12.2  jdolecek 		/* go through each interface addresses */
   3617  1.12.12.2  jdolecek 		IFADDR_READER_FOREACH(ifa, ifn) {
   3618  1.12.12.2  jdolecek 			/* correct family? */
   3619  1.12.12.2  jdolecek 			if (ifa->ifa_addr->sa_family != sa->sa_family)
   3620  1.12.12.2  jdolecek 				continue;
   3621  1.12.12.2  jdolecek 
   3622  1.12.12.2  jdolecek #ifdef INET6
   3623  1.12.12.2  jdolecek 			if (ifa->ifa_addr->sa_family == AF_INET6) {
   3624  1.12.12.2  jdolecek 				/* IPv6 address */
   3625  1.12.12.2  jdolecek 				struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
   3626  1.12.12.2  jdolecek 				sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
   3627  1.12.12.2  jdolecek 				if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
   3628  1.12.12.2  jdolecek 					/* create a copy and clear scope */
   3629  1.12.12.2  jdolecek 					memcpy(&sin6_tmp, sin1,
   3630  1.12.12.2  jdolecek 					    sizeof(struct sockaddr_in6));
   3631  1.12.12.2  jdolecek 					sin1 = &sin6_tmp;
   3632  1.12.12.2  jdolecek 					in6_clearscope(&sin1->sin6_addr);
   3633  1.12.12.2  jdolecek 				}
   3634  1.12.12.2  jdolecek 				sin2 = (struct sockaddr_in6 *)sa;
   3635  1.12.12.2  jdolecek 				if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
   3636  1.12.12.2  jdolecek 					   sizeof(struct in6_addr)) == 0) {
   3637  1.12.12.2  jdolecek 					/* found it */
   3638  1.12.12.2  jdolecek 					pserialize_read_exit(s);
   3639  1.12.12.2  jdolecek 					return (ifa);
   3640  1.12.12.2  jdolecek 				}
   3641  1.12.12.2  jdolecek 			} else
   3642  1.12.12.2  jdolecek #endif
   3643  1.12.12.2  jdolecek 			if (ifa->ifa_addr->sa_family == AF_INET) {
   3644  1.12.12.2  jdolecek 				/* IPv4 address */
   3645  1.12.12.2  jdolecek 				struct sockaddr_in *sin1, *sin2;
   3646  1.12.12.2  jdolecek 				sin1 = (struct sockaddr_in *)ifa->ifa_addr;
   3647  1.12.12.2  jdolecek 				sin2 = (struct sockaddr_in *)sa;
   3648  1.12.12.2  jdolecek 				if (sin1->sin_addr.s_addr ==
   3649  1.12.12.2  jdolecek 				    sin2->sin_addr.s_addr) {
   3650  1.12.12.2  jdolecek 					/* found it */
   3651  1.12.12.2  jdolecek 					pserialize_read_exit(s);
   3652  1.12.12.2  jdolecek 					return (ifa);
   3653  1.12.12.2  jdolecek 				}
   3654  1.12.12.2  jdolecek 			}
   3655  1.12.12.2  jdolecek 			/* else, not AF_INET or AF_INET6, so skip */
   3656  1.12.12.2  jdolecek 		} /* end foreach ifa */
   3657  1.12.12.2  jdolecek 	} /* end foreach ifn */
   3658  1.12.12.2  jdolecek 	pserialize_read_exit(s);
   3659  1.12.12.2  jdolecek 
   3660  1.12.12.2  jdolecek 	/* not found! */
   3661  1.12.12.2  jdolecek 	return (NULL);
   3662  1.12.12.2  jdolecek }
   3663  1.12.12.2  jdolecek 
   3664  1.12.12.2  jdolecek 
   3665  1.12.12.2  jdolecek #ifdef __APPLE__
   3666  1.12.12.2  jdolecek /*
   3667  1.12.12.2  jdolecek  * here we hack in a fix for Apple's m_copym for the case where the first mbuf
   3668  1.12.12.2  jdolecek  * in the chain is a M_PKTHDR and the length is zero
   3669  1.12.12.2  jdolecek  */
   3670  1.12.12.2  jdolecek static void
   3671  1.12.12.2  jdolecek sctp_pkthdr_fix(struct mbuf *m)
   3672  1.12.12.2  jdolecek {
   3673  1.12.12.2  jdolecek 	struct mbuf *m_nxt;
   3674  1.12.12.2  jdolecek 
   3675  1.12.12.2  jdolecek 	if ((m->m_flags & M_PKTHDR) == 0) {
   3676  1.12.12.2  jdolecek 		/* not a PKTHDR */
   3677  1.12.12.2  jdolecek 		return;
   3678  1.12.12.2  jdolecek 	}
   3679  1.12.12.2  jdolecek 
   3680  1.12.12.2  jdolecek 	if (m->m_len != 0) {
   3681  1.12.12.2  jdolecek 		/* not a zero length PKTHDR mbuf */
   3682  1.12.12.2  jdolecek 		return;
   3683  1.12.12.2  jdolecek 	}
   3684  1.12.12.2  jdolecek 
   3685  1.12.12.2  jdolecek 	/* let's move in a word into the first mbuf... yes, ugly! */
   3686  1.12.12.2  jdolecek 	m_nxt = m->m_next;
   3687  1.12.12.2  jdolecek 	if (m_nxt == NULL) {
   3688  1.12.12.2  jdolecek 		/* umm... not a very useful mbuf chain... */
   3689  1.12.12.2  jdolecek 		return;
   3690  1.12.12.2  jdolecek 	}
   3691  1.12.12.2  jdolecek 	if ((size_t)m_nxt->m_len > sizeof(long)) {
   3692  1.12.12.2  jdolecek 		/* move over a long */
   3693  1.12.12.2  jdolecek 		bcopy(mtod(m_nxt, void *), mtod(m, void *), sizeof(long));
   3694  1.12.12.2  jdolecek 		/* update mbuf data pointers and lengths */
   3695  1.12.12.2  jdolecek 		m->m_len += sizeof(long);
   3696  1.12.12.2  jdolecek 		m_nxt->m_data += sizeof(long);
   3697  1.12.12.2  jdolecek 		m_nxt->m_len -= sizeof(long);
   3698  1.12.12.2  jdolecek 	}
   3699  1.12.12.2  jdolecek }
   3700  1.12.12.2  jdolecek 
   3701  1.12.12.2  jdolecek inline struct mbuf *
   3702  1.12.12.2  jdolecek sctp_m_copym(struct mbuf *m, int off, int len, int wait)
   3703  1.12.12.2  jdolecek {
   3704  1.12.12.2  jdolecek 	sctp_pkthdr_fix(m);
   3705  1.12.12.2  jdolecek 	return (m_copym(m, off, len, wait));
   3706  1.12.12.2  jdolecek }
   3707  1.12.12.2  jdolecek #endif /* __APPLE__ */
   3708