Deleted Added
sdiff udiff text old ( 166675 ) new ( 167598 )
full compact
1/*-
2 * Copyright (c) 2001-2007, Cisco Systems, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * a) Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.

--- 17 unchanged lines hidden (view full) ---

26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/* $KAME: sctputil.c,v 1.37 2005/03/07 23:26:09 itojun Exp $ */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/netinet/sctputil.c 166675 2007-02-12 23:24:31Z rrs $");
35
36#include <netinet/sctp_os.h>
37#include <netinet/sctp_pcb.h>
38#include <netinet/sctputil.h>
39#include <netinet/sctp_var.h>
40#ifdef INET6
41#include <netinet6/sctp6_var.h>
42#endif
43#include <netinet/sctp_header.h>
44#include <netinet/sctp_output.h>
45#include <netinet/sctp_uio.h>
46#include <netinet/sctp_timer.h>
47#include <netinet/sctp_crc32.h>
48#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
49#include <netinet/sctp_auth.h>
50#include <netinet/sctp_asconf.h>
51
52extern int sctp_warm_the_crc32_table;
53
54#define NUMBER_OF_MTU_SIZES 18
55
56#ifdef SCTP_DEBUG
57extern uint32_t sctp_debug_on;
58
59#endif
60
61
62#ifdef SCTP_STAT_LOGGING
63int global_sctp_cwnd_log_at = 0;
64int global_sctp_cwnd_log_rolled = 0;
65struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE];
66
67static uint32_t
68sctp_get_time_of_event(void)
69{

--- 414 unchanged lines hidden (view full) ---

484 sctp_clog[sctp_cwnd_log_at].x.blk.peer_rwnd = asoc->peers_rwnd;
485 sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
486 sctp_clog[sctp_cwnd_log_at].x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
487 sctp_clog[sctp_cwnd_log_at].x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024);
488 sctp_clog[sctp_cwnd_log_at].x.blk.sndlen = sendlen;
489}
490
491int
492sctp_fill_stat_log(struct mbuf *m)
493{
494 int sctp_cwnd_log_at;
495 struct sctp_cwnd_log_req *req;
496 size_t size_limit;
497 int num, i, at, cnt_out = 0;
498
499 if (m == NULL)
500 return (EINVAL);
501
502 size_limit = (SCTP_BUF_LEN(m) - sizeof(struct sctp_cwnd_log_req));
503 if (size_limit < sizeof(struct sctp_cwnd_log)) {
504 return (EINVAL);
505 }
506 sctp_cwnd_log_at = global_sctp_cwnd_log_at;
507 req = mtod(m, struct sctp_cwnd_log_req *);
508 num = size_limit / sizeof(struct sctp_cwnd_log);
509 if (global_sctp_cwnd_log_rolled) {
510 req->num_in_log = SCTP_STAT_LOG_SIZE;
511 } else {
512 req->num_in_log = sctp_cwnd_log_at;
513 /*
514 * if the log has not rolled, we don't let you have old
515 * data.

--- 48 unchanged lines hidden (view full) ---

564#endif
565 for (i = 0, at = req->start_at; i < req->num_ret; i++) {
566 req->log[i] = sctp_clog[at];
567 cnt_out++;
568 at++;
569 if (at >= SCTP_STAT_LOG_SIZE)
570 at = 0;
571 }
572 SCTP_BUF_LEN(m) = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req);
573 return (0);
574}
575
576#endif
577
578#ifdef SCTP_AUDITING_ENABLED
579uint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
580static int sctp_audit_indx = 0;

--- 323 unchanged lines hidden (view full) ---

904 }
905 }
906 return (x);
907}
908
909
910int
911sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
912 int for_a_init, uint32_t override_tag)
913{
914 /*
915 * Anything set to zero is taken care of by the allocation routine's
916 * bzero
917 */
918
919 /*
920 * Up front select what scoping to apply on addresses I tell my peer

--- 4 unchanged lines hidden (view full) ---

925 int i;
926
927 /* init all variables to a known value. */
928 asoc->state = SCTP_STATE_INUSE;
929 asoc->max_burst = m->sctp_ep.max_burst;
930 asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
931 asoc->cookie_life = m->sctp_ep.def_cookie_life;
932 asoc->sctp_cmt_on_off = (uint8_t) sctp_cmt_on_off;
933#ifdef AF_INET
934 asoc->default_tos = m->ip_inp.inp.inp_ip_tos;
935#else
936 asoc->default_tos = 0;
937#endif
938
939#ifdef AF_INET6
940 asoc->default_flowlabel = ((struct in6pcb *)m)->in6p_flowinfo;
941#else
942 asoc->default_flowlabel = 0;
943#endif
944 if (override_tag) {
945 struct timeval now;
946
947 SCTP_GETTIME_TIMEVAL(&now);

--- 4 unchanged lines hidden (view full) ---

952 }
953
954 } else {
955 asoc->my_vtag = sctp_select_a_tag(m);
956 }
957 /* Get the nonce tags */
958 asoc->my_vtag_nonce = sctp_select_a_tag(m);
959 asoc->peer_vtag_nonce = sctp_select_a_tag(m);
960
961 if (sctp_is_feature_on(m, SCTP_PCB_FLAGS_DONOT_HEARTBEAT))
962 asoc->hb_is_disabled = 1;
963 else
964 asoc->hb_is_disabled = 0;
965
966 asoc->refcnt = 0;
967 asoc->assoc_up_sent = 0;

--- 32 unchanged lines hidden (view full) ---

1000 asoc->ecn_nonce_allowed = 0;
1001 asoc->receiver_nonce_sum = 1;
1002 asoc->nonce_sum_expect_base = 1;
1003 asoc->nonce_sum_check = 1;
1004 asoc->nonce_resync_tsn = 0;
1005 asoc->nonce_wait_for_ecne = 0;
1006 asoc->nonce_wait_tsn = 0;
1007 asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
1008 asoc->pr_sctp_cnt = 0;
1009 asoc->total_output_queue_size = 0;
1010
1011 if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1012 struct in6pcb *inp6;
1013
1014 /* Its a V6 socket */
1015 inp6 = (struct in6pcb *)m;

--- 18 unchanged lines hidden (view full) ---

1034 asoc->minrto = m->sctp_ep.sctp_minrto;
1035 asoc->maxrto = m->sctp_ep.sctp_maxrto;
1036
1037 asoc->locked_on_sending = NULL;
1038 asoc->stream_locked_on = 0;
1039 asoc->ecn_echo_cnt_onq = 0;
1040 asoc->stream_locked = 0;
1041
1042 LIST_INIT(&asoc->sctp_local_addr_list);
1043 TAILQ_INIT(&asoc->nets);
1044 TAILQ_INIT(&asoc->pending_reply_queue);
1045 asoc->last_asconf_ack_sent = NULL;
1046 /* Setup to fill the hb random cache at first HB */
1047 asoc->hb_random_idx = 4;
1048
1049 asoc->sctp_autoclose_ticks = m->sctp_ep.auto_close_time;
1050

--- 85 unchanged lines hidden (view full) ---

1136 memset(new_array, 0, new_size);
1137 memcpy(new_array, asoc->mapping_array, asoc->mapping_array_size);
1138 SCTP_FREE(asoc->mapping_array);
1139 asoc->mapping_array = new_array;
1140 asoc->mapping_array_size = new_size;
1141 return (0);
1142}
1143
1144extern unsigned int sctp_early_fr_msec;
1145
1146static void
1147sctp_handle_addr_wq(void)
1148{
1149 /* deal with the ADDR wq from the rtsock calls */
1150 struct sctp_laddr *wi;
1151
1152 SCTP_IPI_ADDR_LOCK();
1153 wi = LIST_FIRST(&sctppcbinfo.addr_wq);
1154 if (wi == NULL) {
1155 SCTP_IPI_ADDR_UNLOCK();
1156 return;
1157 }
1158 LIST_REMOVE(wi, sctp_nxt_addr);
1159 if (!SCTP_LIST_EMPTY(&sctppcbinfo.addr_wq)) {
1160 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
1161 (struct sctp_inpcb *)NULL,
1162 (struct sctp_tcb *)NULL,
1163 (struct sctp_nets *)NULL);
1164 }
1165 SCTP_IPI_ADDR_UNLOCK();
1166 if (wi->action == RTM_ADD) {
1167 sctp_add_ip_address(wi->ifa);
1168 } else if (wi->action == RTM_DELETE) {
1169 sctp_delete_ip_address(wi->ifa);
1170 }
1171 IFAFREE(wi->ifa);
1172 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_laddr, wi);
1173 SCTP_DECR_LADDR_COUNT();
1174}
1175
1176void
1177sctp_timeout_handler(void *t)
1178{
1179 struct sctp_inpcb *inp;
1180 struct sctp_tcb *stcb;
1181 struct sctp_nets *net;

--- 377 unchanged lines hidden (view full) ---

1559 tmr = NULL;
1560 if (stcb) {
1561 SCTP_TCB_LOCK_ASSERT(stcb);
1562 }
1563 switch (t_type) {
1564 case SCTP_TIMER_TYPE_ADDR_WQ:
1565 /* Only 1 tick away :-) */
1566 tmr = &sctppcbinfo.addr_wq_timer;
1567 to_ticks = 1;
1568 break;
1569 case SCTP_TIMER_TYPE_ITERATOR:
1570 {
1571 struct sctp_iterator *it;
1572
1573 it = (struct sctp_iterator *)inp;
1574 tmr = &it->tmr;
1575 to_ticks = SCTP_ITERATOR_TICKS;

--- 77 unchanged lines hidden (view full) ---

1653 if (cnt_of_unconf) {
1654 lnet = NULL;
1655 sctp_heartbeat_timer(inp, stcb, lnet, cnt_of_unconf);
1656 }
1657 if (stcb->asoc.hb_random_idx > 3) {
1658 rndval = sctp_select_initial_TSN(&inp->sctp_ep);
1659 memcpy(stcb->asoc.hb_random_values, &rndval,
1660 sizeof(stcb->asoc.hb_random_values));
1661 this_random = stcb->asoc.hb_random_values[0];
1662 stcb->asoc.hb_random_idx = 0;
1663 stcb->asoc.hb_ect_randombit = 0;
1664 } else {
1665 this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
1666 stcb->asoc.hb_random_idx++;
1667 stcb->asoc.hb_ect_randombit = 0;
1668 }
1669 /*
1670 * this_random will be 0 - 256 ms RTO is in ms.
1671 */
1672 if ((stcb->asoc.hb_is_disabled) &&
1673 (cnt_of_unconf == 0)) {
1674 return (0);
1675 }
1676 if (net) {

--- 949 unchanged lines hidden (view full) ---

2626 spc->spc_length = sizeof(struct sctp_paddr_change);
2627 if (sa->sa_family == AF_INET) {
2628 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
2629 } else {
2630 struct sockaddr_in6 *sin6;
2631
2632 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
2633
2634 /* recover scope_id for user */
2635 sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
2636 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
2637 (void)sa6_recoverscope(sin6);
2638 }
2639 }
2640 spc->spc_state = state;
2641 spc->spc_error = error;
2642 spc->spc_assoc_id = sctp_get_associd(stcb);
2643
2644 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change);
2645 SCTP_BUF_NEXT(m_notify) = NULL;

--- 1068 unchanged lines hidden (view full) ---

3714 if (inp == NULL) {
3715 /* Gak, TSNH!! */
3716#ifdef INVARIANTS
3717 panic("Gak, inp NULL on add_to_readq");
3718#endif
3719 return;
3720 }
3721 SCTP_INP_READ_LOCK(inp);
3722 atomic_add_int(&inp->total_recvs, 1);
3723 atomic_add_int(&stcb->total_recvs, 1);
3724 m = control->data;
3725 control->held_length = 0;
3726 control->length = 0;
3727 while (m) {
3728 if (SCTP_BUF_LEN(m) == 0) {
3729 /* Skip mbufs with NO length */
3730 if (prev == NULL) {
3731 /* First one */

--- 282 unchanged lines hidden (view full) ---

4014}
4015
4016/*
4017 * checks to see if the given address, sa, is one that is currently known by
4018 * the kernel note: can't distinguish the same address on multiple interfaces
4019 * and doesn't handle multiple addresses with different zone/scope id's note:
4020 * ifa_ifwithaddr() compares the entire sockaddr struct
4021 */
4022struct ifaddr *
4023sctp_find_ifa_by_addr(struct sockaddr *sa)
4024{
4025 struct ifnet *ifn;
4026 struct ifaddr *ifa;
4027
4028 /* go through all our known interfaces */
4029 TAILQ_FOREACH(ifn, &ifnet, if_list) {
4030 /* go through each interface addresses */
4031 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
4032 /* correct family? */
4033 if (ifa->ifa_addr->sa_family != sa->sa_family)
4034 continue;
4035
4036#ifdef INET6
4037 if (ifa->ifa_addr->sa_family == AF_INET6) {
4038 /* IPv6 address */
4039 struct sockaddr_in6 *sin1, *sin2, sin6_tmp;
4040
4041 sin1 = (struct sockaddr_in6 *)ifa->ifa_addr;
4042 if (IN6_IS_SCOPE_LINKLOCAL(&sin1->sin6_addr)) {
4043 /* create a copy and clear scope */
4044 memcpy(&sin6_tmp, sin1,
4045 sizeof(struct sockaddr_in6));
4046 sin1 = &sin6_tmp;
4047 in6_clearscope(&sin1->sin6_addr);
4048 }
4049 sin2 = (struct sockaddr_in6 *)sa;
4050 if (memcmp(&sin1->sin6_addr, &sin2->sin6_addr,
4051 sizeof(struct in6_addr)) == 0) {
4052 /* found it */
4053 return (ifa);
4054 }
4055 } else
4056#endif
4057 if (ifa->ifa_addr->sa_family == AF_INET) {
4058 /* IPv4 address */
4059 struct sockaddr_in *sin1, *sin2;
4060
4061 sin1 = (struct sockaddr_in *)ifa->ifa_addr;
4062 sin2 = (struct sockaddr_in *)sa;
4063 if (sin1->sin_addr.s_addr ==
4064 sin2->sin_addr.s_addr) {
4065 /* found it */
4066 return (ifa);
4067 }
4068 }
4069 /* else, not AF_INET or AF_INET6, so skip */
4070 } /* end foreach ifa */
4071 } /* end foreach ifn */
4072 /* not found! */
4073 return (NULL);
4074}
4075
4076static void
4077sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock,
4078 uint32_t rwnd_req)
4079{
4080 /* User pulled some data, do we need a rwnd update? */
4081 int r_unlocked = 0;
4082 uint32_t dif, rwnd;
4083 struct socket *so = NULL;

--- 119 unchanged lines hidden (view full) ---

4203 int block_allowed = 1;
4204 int freed_so_far = 0;
4205 int copied_so_far = 0;
4206 int in_eeor_mode = 0;
4207 int no_rcv_needed = 0;
4208 uint32_t rwnd_req = 0;
4209 int hold_sblock = 0;
4210 int hold_rlock = 0;
4211 int alen = 0, slen = 0;
4212 int held_length = 0;
4213
4214 if (msg_flags) {
4215 in_flags = *msg_flags;
4216 } else {
4217 in_flags = 0;
4218 }
4219 slen = uio->uio_resid;
4220 /* Pull in and set up our int flags */
4221 if (in_flags & MSG_OOB) {
4222 /* Out of band's NOT supported */
4223 return (EOPNOTSUPP);
4224 }
4225 if ((in_flags & MSG_PEEK) && (mp != NULL)) {
4226 return (EINVAL);
4227 }
4228 if ((in_flags & (MSG_DONTWAIT
4229 | MSG_NBIO
4230 )) ||
4231 (so->so_state & SS_NBIO)) {
4232 block_allowed = 0;
4233 }
4234 /* setup the endpoint */
4235 inp = (struct sctp_inpcb *)so->so_pcb;
4236 if (inp == NULL) {
4237 return (EFAULT);
4238 }
4239 rwnd_req = (so->so_rcv.sb_hiwat >> SCTP_RWND_HIWAT_SHIFT);

--- 328 unchanged lines hidden (view full) ---

4568 * mask off the high bits, we keep the actual chunk bits in
4569 * there.
4570 */
4571 sinfo->sinfo_flags &= 0x00ff;
4572 }
4573 if (fromlen && from) {
4574 struct sockaddr *to;
4575
4576#ifdef AF_INET
4577 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin.sin_len);
4578 memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
4579 ((struct sockaddr_in *)from)->sin_port = control->port_from;
4580#else
4581 /* No AF_INET use AF_INET6 */
4582 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin6.sin6_len);
4583 memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
4584 ((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
4585#endif
4586
4587 to = from;
4588#if defined(AF_INET) && defined(AF_INET6)
4589 if ((inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
4590 (to->sa_family == AF_INET) &&
4591 ((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
4592 struct sockaddr_in *sin;
4593 struct sockaddr_in6 sin6;
4594
4595 sin = (struct sockaddr_in *)to;
4596 bzero(&sin6, sizeof(sin6));
4597 sin6.sin6_family = AF_INET6;
4598 sin6.sin6_len = sizeof(struct sockaddr_in6);
4599 sin6.sin6_addr.s6_addr16[2] = 0xffff;
4600 bcopy(&sin->sin_addr,
4601 &sin6.sin6_addr.s6_addr16[3],
4602 sizeof(sin6.sin6_addr.s6_addr16[3]));
4603 sin6.sin6_port = sin->sin_port;
4604 memcpy(from, (caddr_t)&sin6, sizeof(sin6));
4605 }
4606#endif
4607#if defined(AF_INET6)
4608 {
4609 struct sockaddr_in6 lsa6, *to6;
4610
4611 to6 = (struct sockaddr_in6 *)to;
4612 sctp_recover_scope_mac(to6, (&lsa6));
4613 }
4614#endif
4615 }

--- 632 unchanged lines hidden (view full) ---

5248sctp_m_freem(struct mbuf *mb)
5249{
5250 while (mb != NULL)
5251 mb = sctp_m_free(mb);
5252}
5253
5254#endif
5255
5256
5257int
5258sctp_soreceive(so, psa, uio, mp0, controlp, flagsp)
5259 struct socket *so;
5260 struct sockaddr **psa;
5261 struct uio *uio;
5262 struct mbuf **mp0;
5263 struct mbuf **controlp;
5264 int *flagsp;

--- 48 unchanged lines hidden ---