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 167598 2007-03-15 11:27:14Z 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#include <netinet/sctp_sysctl.h>
41#ifdef INET6
42#include <netinet6/sctp6_var.h>
43#endif
44#include <netinet/sctp_header.h>
45#include <netinet/sctp_output.h>
46#include <netinet/sctp_uio.h>
47#include <netinet/sctp_timer.h>
48#include <netinet/sctp_crc32.h>
49#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
50#include <netinet/sctp_auth.h>
51#include <netinet/sctp_asconf.h>
52#include <netinet/sctp_bsd_addr.h>
53
54#define NUMBER_OF_MTU_SIZES 18
55
56
57#ifdef SCTP_STAT_LOGGING
58int global_sctp_cwnd_log_at = 0;
59int global_sctp_cwnd_log_rolled = 0;
60struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE];
61
62static uint32_t
63sctp_get_time_of_event(void)
64{
--- 414 unchanged lines hidden (view full) ---
479 sctp_clog[sctp_cwnd_log_at].x.blk.peer_rwnd = asoc->peers_rwnd;
480 sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
481 sctp_clog[sctp_cwnd_log_at].x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
482 sctp_clog[sctp_cwnd_log_at].x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024);
483 sctp_clog[sctp_cwnd_log_at].x.blk.sndlen = sendlen;
484}
485
486int
487sctp_fill_stat_log(void *optval, size_t *optsize)
488{
489 int sctp_cwnd_log_at;
490 struct sctp_cwnd_log_req *req;
491 size_t size_limit;
492 int num, i, at, cnt_out = 0;
493
494 if (*optsize < sizeof(struct sctp_cwnd_log_req)) {
495 return (EINVAL);
496 }
497 size_limit = (*optsize - sizeof(struct sctp_cwnd_log_req));
498 if (size_limit < sizeof(struct sctp_cwnd_log)) {
499 return (EINVAL);
500 }
501 sctp_cwnd_log_at = global_sctp_cwnd_log_at;
502 req = (struct sctp_cwnd_log_req *)optval;
503 num = size_limit / sizeof(struct sctp_cwnd_log);
504 if (global_sctp_cwnd_log_rolled) {
505 req->num_in_log = SCTP_STAT_LOG_SIZE;
506 } else {
507 req->num_in_log = sctp_cwnd_log_at;
508 /*
509 * if the log has not rolled, we don't let you have old
510 * data.
--- 48 unchanged lines hidden (view full) ---
559#endif
560 for (i = 0, at = req->start_at; i < req->num_ret; i++) {
561 req->log[i] = sctp_clog[at];
562 cnt_out++;
563 at++;
564 if (at >= SCTP_STAT_LOG_SIZE)
565 at = 0;
566 }
567 *optsize = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req);
568 return (0);
569}
570
571#endif
572
573#ifdef SCTP_AUDITING_ENABLED
574uint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
575static int sctp_audit_indx = 0;
--- 323 unchanged lines hidden (view full) ---
899 }
900 }
901 return (x);
902}
903
904
905int
906sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
907 int for_a_init, uint32_t override_tag, uint32_t vrf_id)
908{
909 /*
910 * Anything set to zero is taken care of by the allocation routine's
911 * bzero
912 */
913
914 /*
915 * Up front select what scoping to apply on addresses I tell my peer
--- 4 unchanged lines hidden (view full) ---
920 int i;
921
922 /* init all variables to a known value. */
923 asoc->state = SCTP_STATE_INUSE;
924 asoc->max_burst = m->sctp_ep.max_burst;
925 asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
926 asoc->cookie_life = m->sctp_ep.def_cookie_life;
927 asoc->sctp_cmt_on_off = (uint8_t) sctp_cmt_on_off;
928#ifdef INET
929 asoc->default_tos = m->ip_inp.inp.inp_ip_tos;
930#else
931 asoc->default_tos = 0;
932#endif
933
934#ifdef INET6
935 asoc->default_flowlabel = ((struct in6pcb *)m)->in6p_flowinfo;
936#else
937 asoc->default_flowlabel = 0;
938#endif
939 if (override_tag) {
940 struct timeval now;
941
942 SCTP_GETTIME_TIMEVAL(&now);
--- 4 unchanged lines hidden (view full) ---
947 }
948
949 } else {
950 asoc->my_vtag = sctp_select_a_tag(m);
951 }
952 /* Get the nonce tags */
953 asoc->my_vtag_nonce = sctp_select_a_tag(m);
954 asoc->peer_vtag_nonce = sctp_select_a_tag(m);
955 asoc->vrf_id = vrf_id;
956
957 if (sctp_is_feature_on(m, SCTP_PCB_FLAGS_DONOT_HEARTBEAT))
958 asoc->hb_is_disabled = 1;
959 else
960 asoc->hb_is_disabled = 0;
961
962 asoc->refcnt = 0;
963 asoc->assoc_up_sent = 0;
--- 32 unchanged lines hidden (view full) ---
996 asoc->ecn_nonce_allowed = 0;
997 asoc->receiver_nonce_sum = 1;
998 asoc->nonce_sum_expect_base = 1;
999 asoc->nonce_sum_check = 1;
1000 asoc->nonce_resync_tsn = 0;
1001 asoc->nonce_wait_for_ecne = 0;
1002 asoc->nonce_wait_tsn = 0;
1003 asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
1004 asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
1005 asoc->pr_sctp_cnt = 0;
1006 asoc->total_output_queue_size = 0;
1007
1008 if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1009 struct in6pcb *inp6;
1010
1011 /* Its a V6 socket */
1012 inp6 = (struct in6pcb *)m;
--- 18 unchanged lines hidden (view full) ---
1031 asoc->minrto = m->sctp_ep.sctp_minrto;
1032 asoc->maxrto = m->sctp_ep.sctp_maxrto;
1033
1034 asoc->locked_on_sending = NULL;
1035 asoc->stream_locked_on = 0;
1036 asoc->ecn_echo_cnt_onq = 0;
1037 asoc->stream_locked = 0;
1038
1039 asoc->send_sack = 1;
1040
1041 LIST_INIT(&asoc->sctp_restricted_addrs);
1042
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
1144#if defined(SCTP_USE_THREAD_BASED_ITERATOR)
1145static void
1146sctp_iterator_work(struct sctp_iterator *it)
1147{
1148 int iteration_count = 0;
1149 int inp_skip = 0;
1150
1151 SCTP_ITERATOR_LOCK();
1152 if (it->inp)
1153 SCTP_INP_DECR_REF(it->inp);
1154
1155 if (it->inp == NULL) {
1156 /* iterator is complete */
1157done_with_iterator:
1158 SCTP_ITERATOR_UNLOCK();
1159 if (it->function_atend != NULL) {
1160 (*it->function_atend) (it->pointer, it->val);
1161 }
1162 SCTP_FREE(it);
1163 return;
1164 }
1165select_a_new_ep:
1166 SCTP_INP_WLOCK(it->inp);
1167 while (((it->pcb_flags) &&
1168 ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
1169 ((it->pcb_features) &&
1170 ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
1171 /* endpoint flags or features don't match, so keep looking */
1172 if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1173 SCTP_INP_WUNLOCK(it->inp);
1174 goto done_with_iterator;
1175 }
1176 SCTP_INP_WUNLOCK(it->inp);
1177 it->inp = LIST_NEXT(it->inp, sctp_list);
1178 if (it->inp == NULL) {
1179 goto done_with_iterator;
1180 }
1181 SCTP_INP_WLOCK(it->inp);
1182 }
1183
1184 /* mark the current iterator on the endpoint */
1185 it->inp->inp_starting_point_for_iterator = it;
1186 SCTP_INP_WUNLOCK(it->inp);
1187 SCTP_INP_RLOCK(it->inp);
1188
1189 /* now go through each assoc which is in the desired state */
1190 if (it->done_current_ep == 0) {
1191 if (it->function_inp != NULL)
1192 inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val);
1193 it->done_current_ep = 1;
1194 }
1195 if (it->stcb == NULL) {
1196 /* run the per instance function */
1197 it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
1198 }
1199 if ((inp_skip) || it->stcb == NULL) {
1200 if (it->function_inp_end != NULL) {
1201 inp_skip = (*it->function_inp_end) (it->inp,
1202 it->pointer,
1203 it->val);
1204 }
1205 SCTP_INP_RUNLOCK(it->inp);
1206 goto no_stcb;
1207 }
1208 if ((it->stcb) &&
1209 (it->stcb->asoc.stcb_starting_point_for_iterator == it)) {
1210 it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
1211 }
1212 while (it->stcb) {
1213 SCTP_TCB_LOCK(it->stcb);
1214 if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
1215 /* not in the right state... keep looking */
1216 SCTP_TCB_UNLOCK(it->stcb);
1217 goto next_assoc;
1218 }
1219 /* mark the current iterator on the assoc */
1220 it->stcb->asoc.stcb_starting_point_for_iterator = it;
1221 /* see if we have limited out the iterator loop */
1222 iteration_count++;
1223 if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
1224 /* Pause to let others grab the lock */
1225 atomic_add_int(&it->stcb->asoc.refcnt, 1);
1226 SCTP_TCB_UNLOCK(it->stcb);
1227 SCTP_INP_RUNLOCK(it->inp);
1228 SCTP_ITERATOR_UNLOCK();
1229 SCTP_ITERATOR_LOCK();
1230 SCTP_INP_RLOCK(it->inp);
1231 SCTP_TCB_LOCK(it->stcb);
1232 atomic_add_int(&it->stcb->asoc.refcnt, -1);
1233 iteration_count = 0;
1234 }
1235 /* run function on this one */
1236 (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val);
1237
1238 /*
1239 * we lie here, it really needs to have its own type but
1240 * first I must verify that this won't effect things :-0
1241 */
1242 if (it->no_chunk_output == 0)
1243 sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3);
1244
1245 SCTP_TCB_UNLOCK(it->stcb);
1246next_assoc:
1247 it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
1248 if (it->stcb == NULL) {
1249 /* Run last function */
1250 if (it->function_inp_end != NULL) {
1251 inp_skip = (*it->function_inp_end) (it->inp,
1252 it->pointer,
1253 it->val);
1254 }
1255 }
1256 }
1257 SCTP_INP_RUNLOCK(it->inp);
1258no_stcb:
1259 /* done with all assocs on this endpoint, move on to next endpoint */
1260 it->done_current_ep = 0;
1261 SCTP_INP_WLOCK(it->inp);
1262 it->inp->inp_starting_point_for_iterator = NULL;
1263 SCTP_INP_WUNLOCK(it->inp);
1264 if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1265 it->inp = NULL;
1266 } else {
1267 SCTP_INP_INFO_RLOCK();
1268 it->inp = LIST_NEXT(it->inp, sctp_list);
1269 SCTP_INP_INFO_RUNLOCK();
1270 }
1271 if (it->inp == NULL) {
1272 goto done_with_iterator;
1273 }
1274 goto select_a_new_ep;
1275}
1276
1277void
1278sctp_iterator_worker(void)
1279{
1280 struct sctp_iterator *it = NULL;
1281
1282 /* This function is called with the WQ lock in place */
1283
1284 sctppcbinfo.iterator_running = 1;
1285again:
1286 it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
1287 while (it) {
1288 /* now lets work on this one */
1289 TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
1290 SCTP_IPI_ITERATOR_WQ_UNLOCK();
1291 sctp_iterator_work(it);
1292 SCTP_IPI_ITERATOR_WQ_LOCK();
1293 it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
1294 }
1295 if (TAILQ_FIRST(&sctppcbinfo.iteratorhead)) {
1296 goto again;
1297 }
1298 sctppcbinfo.iterator_running = 0;
1299 return;
1300}
1301
1302#endif
1303
1304
1305static void
1306sctp_handle_addr_wq(void)
1307{
1308 /* deal with the ADDR wq from the rtsock calls */
1309 struct sctp_laddr *wi;
1310 struct sctp_asconf_iterator *asc;
1311
1312 SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
1313 sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR");
1314 if (asc == NULL) {
1315 /* Try later, no memory */
1316 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
1317 (struct sctp_inpcb *)NULL,
1318 (struct sctp_tcb *)NULL,
1319 (struct sctp_nets *)NULL);
1320 return;
1321 }
1322 LIST_INIT(&asc->list_of_work);
1323 asc->cnt = 0;
1324 SCTP_IPI_ITERATOR_WQ_LOCK();
1325 wi = LIST_FIRST(&sctppcbinfo.addr_wq);
1326 while (wi != NULL) {
1327 LIST_REMOVE(wi, sctp_nxt_addr);
1328 LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
1329 asc->cnt++;
1330 wi = LIST_FIRST(&sctppcbinfo.addr_wq);
1331 }
1332 SCTP_IPI_ITERATOR_WQ_UNLOCK();
1333 if (asc->cnt == 0) {
1334 SCTP_FREE(asc);
1335 } else {
1336 sctp_initiate_iterator(sctp_iterator_ep,
1337 sctp_iterator_stcb,
1338 NULL, /* No ep end for boundall */
1339 SCTP_PCB_FLAGS_BOUNDALL,
1340 SCTP_PCB_ANY_FEATURES,
1341 SCTP_ASOC_ANY_STATE, (void *)asc, 0,
1342 sctp_iterator_end, NULL, 0);
1343 }
1344
1345}
1346
1347void
1348sctp_timeout_handler(void *t)
1349{
1350 struct sctp_inpcb *inp;
1351 struct sctp_tcb *stcb;
1352 struct sctp_nets *net;
--- 377 unchanged lines hidden (view full) ---
1730 tmr = NULL;
1731 if (stcb) {
1732 SCTP_TCB_LOCK_ASSERT(stcb);
1733 }
1734 switch (t_type) {
1735 case SCTP_TIMER_TYPE_ADDR_WQ:
1736 /* Only 1 tick away :-) */
1737 tmr = &sctppcbinfo.addr_wq_timer;
1738 to_ticks = SCTP_ADDRESS_TICK_DELAY;
1739 break;
1740 case SCTP_TIMER_TYPE_ITERATOR:
1741 {
1742 struct sctp_iterator *it;
1743
1744 it = (struct sctp_iterator *)inp;
1745 tmr = &it->tmr;
1746 to_ticks = SCTP_ITERATOR_TICKS;
--- 77 unchanged lines hidden (view full) ---
1824 if (cnt_of_unconf) {
1825 lnet = NULL;
1826 sctp_heartbeat_timer(inp, stcb, lnet, cnt_of_unconf);
1827 }
1828 if (stcb->asoc.hb_random_idx > 3) {
1829 rndval = sctp_select_initial_TSN(&inp->sctp_ep);
1830 memcpy(stcb->asoc.hb_random_values, &rndval,
1831 sizeof(stcb->asoc.hb_random_values));
1832 stcb->asoc.hb_random_idx = 0;
1833 }
1834 this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
1835 stcb->asoc.hb_random_idx++;
1836 stcb->asoc.hb_ect_randombit = 0;
1837 /*
1838 * this_random will be 0 - 256 ms RTO is in ms.
1839 */
1840 if ((stcb->asoc.hb_is_disabled) &&
1841 (cnt_of_unconf == 0)) {
1842 return (0);
1843 }
1844 if (net) {
--- 949 unchanged lines hidden (view full) ---
2794 spc->spc_length = sizeof(struct sctp_paddr_change);
2795 if (sa->sa_family == AF_INET) {
2796 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
2797 } else {
2798 struct sockaddr_in6 *sin6;
2799
2800 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
2801
2802 sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
2803 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
2804 if (sin6->sin6_scope_id == 0) {
2805 /* recover scope_id for user */
2806 (void)sa6_recoverscope(sin6);
2807 } else {
2808 /* clear embedded scope_id for user */
2809 in6_clearscope(&sin6->sin6_addr);
2810 }
2811 }
2812 }
2813 spc->spc_state = state;
2814 spc->spc_error = error;
2815 spc->spc_assoc_id = sctp_get_associd(stcb);
2816
2817 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change);
2818 SCTP_BUF_NEXT(m_notify) = NULL;
--- 1068 unchanged lines hidden (view full) ---
3887 if (inp == NULL) {
3888 /* Gak, TSNH!! */
3889#ifdef INVARIANTS
3890 panic("Gak, inp NULL on add_to_readq");
3891#endif
3892 return;
3893 }
3894 SCTP_INP_READ_LOCK(inp);
3895 if (!(control->spec_flags & M_NOTIFICATION)) {
3896 atomic_add_int(&inp->total_recvs, 1);
3897 if (!control->do_not_ref_stcb) {
3898 atomic_add_int(&stcb->total_recvs, 1);
3899 }
3900 }
3901 m = control->data;
3902 control->held_length = 0;
3903 control->length = 0;
3904 while (m) {
3905 if (SCTP_BUF_LEN(m) == 0) {
3906 /* Skip mbufs with NO length */
3907 if (prev == NULL) {
3908 /* First one */
--- 282 unchanged lines hidden (view full) ---
4191}
4192
4193/*
4194 * checks to see if the given address, sa, is one that is currently known by
4195 * the kernel note: can't distinguish the same address on multiple interfaces
4196 * and doesn't handle multiple addresses with different zone/scope id's note:
4197 * ifa_ifwithaddr() compares the entire sockaddr struct
4198 */
4199struct sctp_ifa *
4200sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int holds_lock)
4201{
4202 struct sctp_laddr *laddr;
4203
4204 if (holds_lock == 0)
4205 SCTP_INP_RLOCK(inp);
4206
4207 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
4208 if (laddr->ifa == NULL)
4209 continue;
4210 if (addr->sa_family != laddr->ifa->address.sa.sa_family)
4211 continue;
4212 if (addr->sa_family == AF_INET) {
4213 if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
4214 laddr->ifa->address.sin.sin_addr.s_addr) {
4215 /* found him. */
4216 if (holds_lock == 0)
4217 SCTP_INP_RUNLOCK(inp);
4218 return (laddr->ifa);
4219 break;
4220 }
4221 } else if (addr->sa_family == AF_INET6) {
4222 if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
4223 &laddr->ifa->address.sin6.sin6_addr)) {
4224 /* found him. */
4225 if (holds_lock == 0)
4226 SCTP_INP_RUNLOCK(inp);
4227 return (laddr->ifa);
4228 break;
4229 }
4230 }
4231 }
4232 if (holds_lock == 0)
4233 SCTP_INP_RUNLOCK(inp);
4234 return (NULL);
4235}
4236
4237struct sctp_ifa *
4238sctp_find_ifa_in_ifn(struct sctp_ifn *sctp_ifnp, struct sockaddr *addr,
4239 int holds_lock)
4240{
4241 struct sctp_ifa *sctp_ifap;
4242
4243 if (holds_lock == 0)
4244 SCTP_IPI_ADDR_LOCK();
4245
4246 LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
4247 if (addr->sa_family != sctp_ifap->address.sa.sa_family)
4248 continue;
4249 if (addr->sa_family == AF_INET) {
4250 if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
4251 sctp_ifap->address.sin.sin_addr.s_addr) {
4252 /* found him. */
4253 if (holds_lock == 0)
4254 SCTP_IPI_ADDR_UNLOCK();
4255 return (sctp_ifap);
4256 break;
4257 }
4258 } else if (addr->sa_family == AF_INET6) {
4259 if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
4260 &sctp_ifap->address.sin6.sin6_addr)) {
4261 /* found him. */
4262 if (holds_lock == 0)
4263 SCTP_IPI_ADDR_UNLOCK();
4264 return (sctp_ifap);
4265 break;
4266 }
4267 }
4268 }
4269 if (holds_lock == 0)
4270 SCTP_IPI_ADDR_UNLOCK();
4271 return (NULL);
4272}
4273
4274struct sctp_ifa *
4275sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
4276{
4277 struct sctp_ifa *sctp_ifap;
4278 struct sctp_ifn *sctp_ifnp = NULL;
4279 struct sctp_vrf *vrf;
4280
4281 vrf = sctp_find_vrf(vrf_id);
4282 if (vrf == NULL)
4283 return (NULL);
4284
4285 if (holds_lock == 0)
4286 SCTP_IPI_ADDR_LOCK();
4287
4288 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
4289 sctp_ifap = sctp_find_ifa_in_ifn(sctp_ifnp, addr, 1);
4290 if (sctp_ifap) {
4291 if (holds_lock == 0)
4292 SCTP_IPI_ADDR_UNLOCK();
4293 return (sctp_ifap);
4294 }
4295 }
4296 if (holds_lock == 0)
4297 SCTP_IPI_ADDR_UNLOCK();
4298 return (NULL);
4299}
4300
4301static void
4302sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock,
4303 uint32_t rwnd_req)
4304{
4305 /* User pulled some data, do we need a rwnd update? */
4306 int r_unlocked = 0;
4307 uint32_t dif, rwnd;
4308 struct socket *so = NULL;
--- 119 unchanged lines hidden (view full) ---
4428 int block_allowed = 1;
4429 int freed_so_far = 0;
4430 int copied_so_far = 0;
4431 int in_eeor_mode = 0;
4432 int no_rcv_needed = 0;
4433 uint32_t rwnd_req = 0;
4434 int hold_sblock = 0;
4435 int hold_rlock = 0;
4436 int alen = 0;
4437 int slen = 0;
4438 int held_length = 0;
4439
4440 if (msg_flags) {
4441 in_flags = *msg_flags;
4442 } else {
4443 in_flags = 0;
4444 }
4445 slen = uio->uio_resid;
4446 /* Pull in and set up our int flags */
4447 if (in_flags & MSG_OOB) {
4448 /* Out of band's NOT supported */
4449 return (EOPNOTSUPP);
4450 }
4451 if ((in_flags & MSG_PEEK) && (mp != NULL)) {
4452 return (EINVAL);
4453 }
4454 if ((in_flags & (MSG_DONTWAIT
4455 | MSG_NBIO
4456 )) ||
4457 SCTP_SO_IS_NBIO(so)) {
4458 block_allowed = 0;
4459 }
4460 /* setup the endpoint */
4461 inp = (struct sctp_inpcb *)so->so_pcb;
4462 if (inp == NULL) {
4463 return (EFAULT);
4464 }
4465 rwnd_req = (so->so_rcv.sb_hiwat >> SCTP_RWND_HIWAT_SHIFT);
--- 328 unchanged lines hidden (view full) ---
4794 * mask off the high bits, we keep the actual chunk bits in
4795 * there.
4796 */
4797 sinfo->sinfo_flags &= 0x00ff;
4798 }
4799 if (fromlen && from) {
4800 struct sockaddr *to;
4801
4802#ifdef INET
4803 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin.sin_len);
4804 memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
4805 ((struct sockaddr_in *)from)->sin_port = control->port_from;
4806#else
4807 /* No AF_INET use AF_INET6 */
4808 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin6.sin6_len);
4809 memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
4810 ((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
4811#endif
4812
4813 to = from;
4814#if defined(INET) && defined(INET6)
4815 if ((inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
4816 (to->sa_family == AF_INET) &&
4817 ((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
4818 struct sockaddr_in *sin;
4819 struct sockaddr_in6 sin6;
4820
4821 sin = (struct sockaddr_in *)to;
4822 bzero(&sin6, sizeof(sin6));
4823 sin6.sin6_family = AF_INET6;
4824 sin6.sin6_len = sizeof(struct sockaddr_in6);
4825 sin6.sin6_addr.s6_addr16[2] = 0xffff;
4826 bcopy(&sin->sin_addr,
4827 &sin6.sin6_addr.s6_addr16[3],
4828 sizeof(sin6.sin6_addr.s6_addr16[3]));
4829 sin6.sin6_port = sin->sin_port;
4830 memcpy(from, (caddr_t)&sin6, sizeof(sin6));
4831 }
4832#endif
4833#if defined(INET6)
4834 {
4835 struct sockaddr_in6 lsa6, *to6;
4836
4837 to6 = (struct sockaddr_in6 *)to;
4838 sctp_recover_scope_mac(to6, (&lsa6));
4839 }
4840#endif
4841 }
--- 632 unchanged lines hidden (view full) ---
5474sctp_m_freem(struct mbuf *mb)
5475{
5476 while (mb != NULL)
5477 mb = sctp_m_free(mb);
5478}
5479
5480#endif
5481
5482int
5483sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
5484{
5485 /*
5486 * Given a local address. For all associations that holds the
5487 * address, request a peer-set-primary.
5488 */
5489 struct sctp_ifa *ifa;
5490 struct sctp_laddr *wi;
5491
5492 ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
5493 if (ifa == NULL) {
5494 return (EADDRNOTAVAIL);
5495 }
5496 /*
5497 * Now that we have the ifa we must awaken the iterator with this
5498 * message.
5499 */
5500 wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
5501 if (wi == NULL) {
5502 return (ENOMEM);
5503 }
5504 /* Now incr the count and int wi structure */
5505 SCTP_INCR_LADDR_COUNT();
5506 bzero(wi, sizeof(*wi));
5507 wi->ifa = ifa;
5508 wi->action = SCTP_SET_PRIM_ADDR;
5509 atomic_add_int(&ifa->refcount, 1);
5510
5511 /* Now add it to the work queue */
5512 SCTP_IPI_ITERATOR_WQ_LOCK();
5513 /*
5514 * Should this really be a tailq? As it is we will process the
5515 * newest first :-0
5516 */
5517 LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr);
5518 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
5519 (struct sctp_inpcb *)NULL,
5520 (struct sctp_tcb *)NULL,
5521 (struct sctp_nets *)NULL);
5522 SCTP_IPI_ITERATOR_WQ_UNLOCK();
5523 return (0);
5524}
5525
5526
5527
5528
5529int
5530sctp_soreceive(so, psa, uio, mp0, controlp, flagsp)
5531 struct socket *so;
5532 struct sockaddr **psa;
5533 struct uio *uio;
5534 struct mbuf **mp0;
5535 struct mbuf **controlp;
5536 int *flagsp;
--- 48 unchanged lines hidden ---
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 167598 2007-03-15 11:27:14Z 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#include <netinet/sctp_sysctl.h>
41#ifdef INET6
42#include <netinet6/sctp6_var.h>
43#endif
44#include <netinet/sctp_header.h>
45#include <netinet/sctp_output.h>
46#include <netinet/sctp_uio.h>
47#include <netinet/sctp_timer.h>
48#include <netinet/sctp_crc32.h>
49#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
50#include <netinet/sctp_auth.h>
51#include <netinet/sctp_asconf.h>
52#include <netinet/sctp_bsd_addr.h>
53
54#define NUMBER_OF_MTU_SIZES 18
55
56
57#ifdef SCTP_STAT_LOGGING
58int global_sctp_cwnd_log_at = 0;
59int global_sctp_cwnd_log_rolled = 0;
60struct sctp_cwnd_log sctp_clog[SCTP_STAT_LOG_SIZE];
61
62static uint32_t
63sctp_get_time_of_event(void)
64{
--- 414 unchanged lines hidden (view full) ---
479 sctp_clog[sctp_cwnd_log_at].x.blk.peer_rwnd = asoc->peers_rwnd;
480 sctp_clog[sctp_cwnd_log_at].x.blk.stream_qcnt = (uint16_t) asoc->stream_queue_cnt;
481 sctp_clog[sctp_cwnd_log_at].x.blk.chunks_on_oque = (uint16_t) asoc->chunks_on_out_queue;
482 sctp_clog[sctp_cwnd_log_at].x.blk.flight_size = (uint16_t) (asoc->total_flight / 1024);
483 sctp_clog[sctp_cwnd_log_at].x.blk.sndlen = sendlen;
484}
485
486int
487sctp_fill_stat_log(void *optval, size_t *optsize)
488{
489 int sctp_cwnd_log_at;
490 struct sctp_cwnd_log_req *req;
491 size_t size_limit;
492 int num, i, at, cnt_out = 0;
493
494 if (*optsize < sizeof(struct sctp_cwnd_log_req)) {
495 return (EINVAL);
496 }
497 size_limit = (*optsize - sizeof(struct sctp_cwnd_log_req));
498 if (size_limit < sizeof(struct sctp_cwnd_log)) {
499 return (EINVAL);
500 }
501 sctp_cwnd_log_at = global_sctp_cwnd_log_at;
502 req = (struct sctp_cwnd_log_req *)optval;
503 num = size_limit / sizeof(struct sctp_cwnd_log);
504 if (global_sctp_cwnd_log_rolled) {
505 req->num_in_log = SCTP_STAT_LOG_SIZE;
506 } else {
507 req->num_in_log = sctp_cwnd_log_at;
508 /*
509 * if the log has not rolled, we don't let you have old
510 * data.
--- 48 unchanged lines hidden (view full) ---
559#endif
560 for (i = 0, at = req->start_at; i < req->num_ret; i++) {
561 req->log[i] = sctp_clog[at];
562 cnt_out++;
563 at++;
564 if (at >= SCTP_STAT_LOG_SIZE)
565 at = 0;
566 }
567 *optsize = (cnt_out * sizeof(struct sctp_cwnd_log)) + sizeof(struct sctp_cwnd_log_req);
568 return (0);
569}
570
571#endif
572
573#ifdef SCTP_AUDITING_ENABLED
574uint8_t sctp_audit_data[SCTP_AUDIT_SIZE][2];
575static int sctp_audit_indx = 0;
--- 323 unchanged lines hidden (view full) ---
899 }
900 }
901 return (x);
902}
903
904
905int
906sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
907 int for_a_init, uint32_t override_tag, uint32_t vrf_id)
908{
909 /*
910 * Anything set to zero is taken care of by the allocation routine's
911 * bzero
912 */
913
914 /*
915 * Up front select what scoping to apply on addresses I tell my peer
--- 4 unchanged lines hidden (view full) ---
920 int i;
921
922 /* init all variables to a known value. */
923 asoc->state = SCTP_STATE_INUSE;
924 asoc->max_burst = m->sctp_ep.max_burst;
925 asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
926 asoc->cookie_life = m->sctp_ep.def_cookie_life;
927 asoc->sctp_cmt_on_off = (uint8_t) sctp_cmt_on_off;
928#ifdef INET
929 asoc->default_tos = m->ip_inp.inp.inp_ip_tos;
930#else
931 asoc->default_tos = 0;
932#endif
933
934#ifdef INET6
935 asoc->default_flowlabel = ((struct in6pcb *)m)->in6p_flowinfo;
936#else
937 asoc->default_flowlabel = 0;
938#endif
939 if (override_tag) {
940 struct timeval now;
941
942 SCTP_GETTIME_TIMEVAL(&now);
--- 4 unchanged lines hidden (view full) ---
947 }
948
949 } else {
950 asoc->my_vtag = sctp_select_a_tag(m);
951 }
952 /* Get the nonce tags */
953 asoc->my_vtag_nonce = sctp_select_a_tag(m);
954 asoc->peer_vtag_nonce = sctp_select_a_tag(m);
955 asoc->vrf_id = vrf_id;
956
957 if (sctp_is_feature_on(m, SCTP_PCB_FLAGS_DONOT_HEARTBEAT))
958 asoc->hb_is_disabled = 1;
959 else
960 asoc->hb_is_disabled = 0;
961
962 asoc->refcnt = 0;
963 asoc->assoc_up_sent = 0;
--- 32 unchanged lines hidden (view full) ---
996 asoc->ecn_nonce_allowed = 0;
997 asoc->receiver_nonce_sum = 1;
998 asoc->nonce_sum_expect_base = 1;
999 asoc->nonce_sum_check = 1;
1000 asoc->nonce_resync_tsn = 0;
1001 asoc->nonce_wait_for_ecne = 0;
1002 asoc->nonce_wait_tsn = 0;
1003 asoc->delayed_ack = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
1004 asoc->sack_freq = m->sctp_ep.sctp_sack_freq;
1005 asoc->pr_sctp_cnt = 0;
1006 asoc->total_output_queue_size = 0;
1007
1008 if (m->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1009 struct in6pcb *inp6;
1010
1011 /* Its a V6 socket */
1012 inp6 = (struct in6pcb *)m;
--- 18 unchanged lines hidden (view full) ---
1031 asoc->minrto = m->sctp_ep.sctp_minrto;
1032 asoc->maxrto = m->sctp_ep.sctp_maxrto;
1033
1034 asoc->locked_on_sending = NULL;
1035 asoc->stream_locked_on = 0;
1036 asoc->ecn_echo_cnt_onq = 0;
1037 asoc->stream_locked = 0;
1038
1039 asoc->send_sack = 1;
1040
1041 LIST_INIT(&asoc->sctp_restricted_addrs);
1042
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
1144#if defined(SCTP_USE_THREAD_BASED_ITERATOR)
1145static void
1146sctp_iterator_work(struct sctp_iterator *it)
1147{
1148 int iteration_count = 0;
1149 int inp_skip = 0;
1150
1151 SCTP_ITERATOR_LOCK();
1152 if (it->inp)
1153 SCTP_INP_DECR_REF(it->inp);
1154
1155 if (it->inp == NULL) {
1156 /* iterator is complete */
1157done_with_iterator:
1158 SCTP_ITERATOR_UNLOCK();
1159 if (it->function_atend != NULL) {
1160 (*it->function_atend) (it->pointer, it->val);
1161 }
1162 SCTP_FREE(it);
1163 return;
1164 }
1165select_a_new_ep:
1166 SCTP_INP_WLOCK(it->inp);
1167 while (((it->pcb_flags) &&
1168 ((it->inp->sctp_flags & it->pcb_flags) != it->pcb_flags)) ||
1169 ((it->pcb_features) &&
1170 ((it->inp->sctp_features & it->pcb_features) != it->pcb_features))) {
1171 /* endpoint flags or features don't match, so keep looking */
1172 if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1173 SCTP_INP_WUNLOCK(it->inp);
1174 goto done_with_iterator;
1175 }
1176 SCTP_INP_WUNLOCK(it->inp);
1177 it->inp = LIST_NEXT(it->inp, sctp_list);
1178 if (it->inp == NULL) {
1179 goto done_with_iterator;
1180 }
1181 SCTP_INP_WLOCK(it->inp);
1182 }
1183
1184 /* mark the current iterator on the endpoint */
1185 it->inp->inp_starting_point_for_iterator = it;
1186 SCTP_INP_WUNLOCK(it->inp);
1187 SCTP_INP_RLOCK(it->inp);
1188
1189 /* now go through each assoc which is in the desired state */
1190 if (it->done_current_ep == 0) {
1191 if (it->function_inp != NULL)
1192 inp_skip = (*it->function_inp) (it->inp, it->pointer, it->val);
1193 it->done_current_ep = 1;
1194 }
1195 if (it->stcb == NULL) {
1196 /* run the per instance function */
1197 it->stcb = LIST_FIRST(&it->inp->sctp_asoc_list);
1198 }
1199 if ((inp_skip) || it->stcb == NULL) {
1200 if (it->function_inp_end != NULL) {
1201 inp_skip = (*it->function_inp_end) (it->inp,
1202 it->pointer,
1203 it->val);
1204 }
1205 SCTP_INP_RUNLOCK(it->inp);
1206 goto no_stcb;
1207 }
1208 if ((it->stcb) &&
1209 (it->stcb->asoc.stcb_starting_point_for_iterator == it)) {
1210 it->stcb->asoc.stcb_starting_point_for_iterator = NULL;
1211 }
1212 while (it->stcb) {
1213 SCTP_TCB_LOCK(it->stcb);
1214 if (it->asoc_state && ((it->stcb->asoc.state & it->asoc_state) != it->asoc_state)) {
1215 /* not in the right state... keep looking */
1216 SCTP_TCB_UNLOCK(it->stcb);
1217 goto next_assoc;
1218 }
1219 /* mark the current iterator on the assoc */
1220 it->stcb->asoc.stcb_starting_point_for_iterator = it;
1221 /* see if we have limited out the iterator loop */
1222 iteration_count++;
1223 if (iteration_count > SCTP_ITERATOR_MAX_AT_ONCE) {
1224 /* Pause to let others grab the lock */
1225 atomic_add_int(&it->stcb->asoc.refcnt, 1);
1226 SCTP_TCB_UNLOCK(it->stcb);
1227 SCTP_INP_RUNLOCK(it->inp);
1228 SCTP_ITERATOR_UNLOCK();
1229 SCTP_ITERATOR_LOCK();
1230 SCTP_INP_RLOCK(it->inp);
1231 SCTP_TCB_LOCK(it->stcb);
1232 atomic_add_int(&it->stcb->asoc.refcnt, -1);
1233 iteration_count = 0;
1234 }
1235 /* run function on this one */
1236 (*it->function_assoc) (it->inp, it->stcb, it->pointer, it->val);
1237
1238 /*
1239 * we lie here, it really needs to have its own type but
1240 * first I must verify that this won't effect things :-0
1241 */
1242 if (it->no_chunk_output == 0)
1243 sctp_chunk_output(it->inp, it->stcb, SCTP_OUTPUT_FROM_T3);
1244
1245 SCTP_TCB_UNLOCK(it->stcb);
1246next_assoc:
1247 it->stcb = LIST_NEXT(it->stcb, sctp_tcblist);
1248 if (it->stcb == NULL) {
1249 /* Run last function */
1250 if (it->function_inp_end != NULL) {
1251 inp_skip = (*it->function_inp_end) (it->inp,
1252 it->pointer,
1253 it->val);
1254 }
1255 }
1256 }
1257 SCTP_INP_RUNLOCK(it->inp);
1258no_stcb:
1259 /* done with all assocs on this endpoint, move on to next endpoint */
1260 it->done_current_ep = 0;
1261 SCTP_INP_WLOCK(it->inp);
1262 it->inp->inp_starting_point_for_iterator = NULL;
1263 SCTP_INP_WUNLOCK(it->inp);
1264 if (it->iterator_flags & SCTP_ITERATOR_DO_SINGLE_INP) {
1265 it->inp = NULL;
1266 } else {
1267 SCTP_INP_INFO_RLOCK();
1268 it->inp = LIST_NEXT(it->inp, sctp_list);
1269 SCTP_INP_INFO_RUNLOCK();
1270 }
1271 if (it->inp == NULL) {
1272 goto done_with_iterator;
1273 }
1274 goto select_a_new_ep;
1275}
1276
1277void
1278sctp_iterator_worker(void)
1279{
1280 struct sctp_iterator *it = NULL;
1281
1282 /* This function is called with the WQ lock in place */
1283
1284 sctppcbinfo.iterator_running = 1;
1285again:
1286 it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
1287 while (it) {
1288 /* now lets work on this one */
1289 TAILQ_REMOVE(&sctppcbinfo.iteratorhead, it, sctp_nxt_itr);
1290 SCTP_IPI_ITERATOR_WQ_UNLOCK();
1291 sctp_iterator_work(it);
1292 SCTP_IPI_ITERATOR_WQ_LOCK();
1293 it = TAILQ_FIRST(&sctppcbinfo.iteratorhead);
1294 }
1295 if (TAILQ_FIRST(&sctppcbinfo.iteratorhead)) {
1296 goto again;
1297 }
1298 sctppcbinfo.iterator_running = 0;
1299 return;
1300}
1301
1302#endif
1303
1304
1305static void
1306sctp_handle_addr_wq(void)
1307{
1308 /* deal with the ADDR wq from the rtsock calls */
1309 struct sctp_laddr *wi;
1310 struct sctp_asconf_iterator *asc;
1311
1312 SCTP_MALLOC(asc, struct sctp_asconf_iterator *,
1313 sizeof(struct sctp_asconf_iterator), "SCTP_ASCONF_ITERATOR");
1314 if (asc == NULL) {
1315 /* Try later, no memory */
1316 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
1317 (struct sctp_inpcb *)NULL,
1318 (struct sctp_tcb *)NULL,
1319 (struct sctp_nets *)NULL);
1320 return;
1321 }
1322 LIST_INIT(&asc->list_of_work);
1323 asc->cnt = 0;
1324 SCTP_IPI_ITERATOR_WQ_LOCK();
1325 wi = LIST_FIRST(&sctppcbinfo.addr_wq);
1326 while (wi != NULL) {
1327 LIST_REMOVE(wi, sctp_nxt_addr);
1328 LIST_INSERT_HEAD(&asc->list_of_work, wi, sctp_nxt_addr);
1329 asc->cnt++;
1330 wi = LIST_FIRST(&sctppcbinfo.addr_wq);
1331 }
1332 SCTP_IPI_ITERATOR_WQ_UNLOCK();
1333 if (asc->cnt == 0) {
1334 SCTP_FREE(asc);
1335 } else {
1336 sctp_initiate_iterator(sctp_iterator_ep,
1337 sctp_iterator_stcb,
1338 NULL, /* No ep end for boundall */
1339 SCTP_PCB_FLAGS_BOUNDALL,
1340 SCTP_PCB_ANY_FEATURES,
1341 SCTP_ASOC_ANY_STATE, (void *)asc, 0,
1342 sctp_iterator_end, NULL, 0);
1343 }
1344
1345}
1346
1347void
1348sctp_timeout_handler(void *t)
1349{
1350 struct sctp_inpcb *inp;
1351 struct sctp_tcb *stcb;
1352 struct sctp_nets *net;
--- 377 unchanged lines hidden (view full) ---
1730 tmr = NULL;
1731 if (stcb) {
1732 SCTP_TCB_LOCK_ASSERT(stcb);
1733 }
1734 switch (t_type) {
1735 case SCTP_TIMER_TYPE_ADDR_WQ:
1736 /* Only 1 tick away :-) */
1737 tmr = &sctppcbinfo.addr_wq_timer;
1738 to_ticks = SCTP_ADDRESS_TICK_DELAY;
1739 break;
1740 case SCTP_TIMER_TYPE_ITERATOR:
1741 {
1742 struct sctp_iterator *it;
1743
1744 it = (struct sctp_iterator *)inp;
1745 tmr = &it->tmr;
1746 to_ticks = SCTP_ITERATOR_TICKS;
--- 77 unchanged lines hidden (view full) ---
1824 if (cnt_of_unconf) {
1825 lnet = NULL;
1826 sctp_heartbeat_timer(inp, stcb, lnet, cnt_of_unconf);
1827 }
1828 if (stcb->asoc.hb_random_idx > 3) {
1829 rndval = sctp_select_initial_TSN(&inp->sctp_ep);
1830 memcpy(stcb->asoc.hb_random_values, &rndval,
1831 sizeof(stcb->asoc.hb_random_values));
1832 stcb->asoc.hb_random_idx = 0;
1833 }
1834 this_random = stcb->asoc.hb_random_values[stcb->asoc.hb_random_idx];
1835 stcb->asoc.hb_random_idx++;
1836 stcb->asoc.hb_ect_randombit = 0;
1837 /*
1838 * this_random will be 0 - 256 ms RTO is in ms.
1839 */
1840 if ((stcb->asoc.hb_is_disabled) &&
1841 (cnt_of_unconf == 0)) {
1842 return (0);
1843 }
1844 if (net) {
--- 949 unchanged lines hidden (view full) ---
2794 spc->spc_length = sizeof(struct sctp_paddr_change);
2795 if (sa->sa_family == AF_INET) {
2796 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in));
2797 } else {
2798 struct sockaddr_in6 *sin6;
2799
2800 memcpy(&spc->spc_aaddr, sa, sizeof(struct sockaddr_in6));
2801
2802 sin6 = (struct sockaddr_in6 *)&spc->spc_aaddr;
2803 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
2804 if (sin6->sin6_scope_id == 0) {
2805 /* recover scope_id for user */
2806 (void)sa6_recoverscope(sin6);
2807 } else {
2808 /* clear embedded scope_id for user */
2809 in6_clearscope(&sin6->sin6_addr);
2810 }
2811 }
2812 }
2813 spc->spc_state = state;
2814 spc->spc_error = error;
2815 spc->spc_assoc_id = sctp_get_associd(stcb);
2816
2817 SCTP_BUF_LEN(m_notify) = sizeof(struct sctp_paddr_change);
2818 SCTP_BUF_NEXT(m_notify) = NULL;
--- 1068 unchanged lines hidden (view full) ---
3887 if (inp == NULL) {
3888 /* Gak, TSNH!! */
3889#ifdef INVARIANTS
3890 panic("Gak, inp NULL on add_to_readq");
3891#endif
3892 return;
3893 }
3894 SCTP_INP_READ_LOCK(inp);
3895 if (!(control->spec_flags & M_NOTIFICATION)) {
3896 atomic_add_int(&inp->total_recvs, 1);
3897 if (!control->do_not_ref_stcb) {
3898 atomic_add_int(&stcb->total_recvs, 1);
3899 }
3900 }
3901 m = control->data;
3902 control->held_length = 0;
3903 control->length = 0;
3904 while (m) {
3905 if (SCTP_BUF_LEN(m) == 0) {
3906 /* Skip mbufs with NO length */
3907 if (prev == NULL) {
3908 /* First one */
--- 282 unchanged lines hidden (view full) ---
4191}
4192
4193/*
4194 * checks to see if the given address, sa, is one that is currently known by
4195 * the kernel note: can't distinguish the same address on multiple interfaces
4196 * and doesn't handle multiple addresses with different zone/scope id's note:
4197 * ifa_ifwithaddr() compares the entire sockaddr struct
4198 */
4199struct sctp_ifa *
4200sctp_find_ifa_in_ep(struct sctp_inpcb *inp, struct sockaddr *addr, int holds_lock)
4201{
4202 struct sctp_laddr *laddr;
4203
4204 if (holds_lock == 0)
4205 SCTP_INP_RLOCK(inp);
4206
4207 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
4208 if (laddr->ifa == NULL)
4209 continue;
4210 if (addr->sa_family != laddr->ifa->address.sa.sa_family)
4211 continue;
4212 if (addr->sa_family == AF_INET) {
4213 if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
4214 laddr->ifa->address.sin.sin_addr.s_addr) {
4215 /* found him. */
4216 if (holds_lock == 0)
4217 SCTP_INP_RUNLOCK(inp);
4218 return (laddr->ifa);
4219 break;
4220 }
4221 } else if (addr->sa_family == AF_INET6) {
4222 if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
4223 &laddr->ifa->address.sin6.sin6_addr)) {
4224 /* found him. */
4225 if (holds_lock == 0)
4226 SCTP_INP_RUNLOCK(inp);
4227 return (laddr->ifa);
4228 break;
4229 }
4230 }
4231 }
4232 if (holds_lock == 0)
4233 SCTP_INP_RUNLOCK(inp);
4234 return (NULL);
4235}
4236
4237struct sctp_ifa *
4238sctp_find_ifa_in_ifn(struct sctp_ifn *sctp_ifnp, struct sockaddr *addr,
4239 int holds_lock)
4240{
4241 struct sctp_ifa *sctp_ifap;
4242
4243 if (holds_lock == 0)
4244 SCTP_IPI_ADDR_LOCK();
4245
4246 LIST_FOREACH(sctp_ifap, &sctp_ifnp->ifalist, next_ifa) {
4247 if (addr->sa_family != sctp_ifap->address.sa.sa_family)
4248 continue;
4249 if (addr->sa_family == AF_INET) {
4250 if (((struct sockaddr_in *)addr)->sin_addr.s_addr ==
4251 sctp_ifap->address.sin.sin_addr.s_addr) {
4252 /* found him. */
4253 if (holds_lock == 0)
4254 SCTP_IPI_ADDR_UNLOCK();
4255 return (sctp_ifap);
4256 break;
4257 }
4258 } else if (addr->sa_family == AF_INET6) {
4259 if (SCTP6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *)addr)->sin6_addr,
4260 &sctp_ifap->address.sin6.sin6_addr)) {
4261 /* found him. */
4262 if (holds_lock == 0)
4263 SCTP_IPI_ADDR_UNLOCK();
4264 return (sctp_ifap);
4265 break;
4266 }
4267 }
4268 }
4269 if (holds_lock == 0)
4270 SCTP_IPI_ADDR_UNLOCK();
4271 return (NULL);
4272}
4273
4274struct sctp_ifa *
4275sctp_find_ifa_by_addr(struct sockaddr *addr, uint32_t vrf_id, int holds_lock)
4276{
4277 struct sctp_ifa *sctp_ifap;
4278 struct sctp_ifn *sctp_ifnp = NULL;
4279 struct sctp_vrf *vrf;
4280
4281 vrf = sctp_find_vrf(vrf_id);
4282 if (vrf == NULL)
4283 return (NULL);
4284
4285 if (holds_lock == 0)
4286 SCTP_IPI_ADDR_LOCK();
4287
4288 LIST_FOREACH(sctp_ifnp, &vrf->ifnlist, next_ifn) {
4289 sctp_ifap = sctp_find_ifa_in_ifn(sctp_ifnp, addr, 1);
4290 if (sctp_ifap) {
4291 if (holds_lock == 0)
4292 SCTP_IPI_ADDR_UNLOCK();
4293 return (sctp_ifap);
4294 }
4295 }
4296 if (holds_lock == 0)
4297 SCTP_IPI_ADDR_UNLOCK();
4298 return (NULL);
4299}
4300
4301static void
4302sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock,
4303 uint32_t rwnd_req)
4304{
4305 /* User pulled some data, do we need a rwnd update? */
4306 int r_unlocked = 0;
4307 uint32_t dif, rwnd;
4308 struct socket *so = NULL;
--- 119 unchanged lines hidden (view full) ---
4428 int block_allowed = 1;
4429 int freed_so_far = 0;
4430 int copied_so_far = 0;
4431 int in_eeor_mode = 0;
4432 int no_rcv_needed = 0;
4433 uint32_t rwnd_req = 0;
4434 int hold_sblock = 0;
4435 int hold_rlock = 0;
4436 int alen = 0;
4437 int slen = 0;
4438 int held_length = 0;
4439
4440 if (msg_flags) {
4441 in_flags = *msg_flags;
4442 } else {
4443 in_flags = 0;
4444 }
4445 slen = uio->uio_resid;
4446 /* Pull in and set up our int flags */
4447 if (in_flags & MSG_OOB) {
4448 /* Out of band's NOT supported */
4449 return (EOPNOTSUPP);
4450 }
4451 if ((in_flags & MSG_PEEK) && (mp != NULL)) {
4452 return (EINVAL);
4453 }
4454 if ((in_flags & (MSG_DONTWAIT
4455 | MSG_NBIO
4456 )) ||
4457 SCTP_SO_IS_NBIO(so)) {
4458 block_allowed = 0;
4459 }
4460 /* setup the endpoint */
4461 inp = (struct sctp_inpcb *)so->so_pcb;
4462 if (inp == NULL) {
4463 return (EFAULT);
4464 }
4465 rwnd_req = (so->so_rcv.sb_hiwat >> SCTP_RWND_HIWAT_SHIFT);
--- 328 unchanged lines hidden (view full) ---
4794 * mask off the high bits, we keep the actual chunk bits in
4795 * there.
4796 */
4797 sinfo->sinfo_flags &= 0x00ff;
4798 }
4799 if (fromlen && from) {
4800 struct sockaddr *to;
4801
4802#ifdef INET
4803 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin.sin_len);
4804 memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
4805 ((struct sockaddr_in *)from)->sin_port = control->port_from;
4806#else
4807 /* No AF_INET use AF_INET6 */
4808 cp_len = min(fromlen, control->whoFrom->ro._l_addr.sin6.sin6_len);
4809 memcpy(from, &control->whoFrom->ro._l_addr, cp_len);
4810 ((struct sockaddr_in6 *)from)->sin6_port = control->port_from;
4811#endif
4812
4813 to = from;
4814#if defined(INET) && defined(INET6)
4815 if ((inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
4816 (to->sa_family == AF_INET) &&
4817 ((size_t)fromlen >= sizeof(struct sockaddr_in6))) {
4818 struct sockaddr_in *sin;
4819 struct sockaddr_in6 sin6;
4820
4821 sin = (struct sockaddr_in *)to;
4822 bzero(&sin6, sizeof(sin6));
4823 sin6.sin6_family = AF_INET6;
4824 sin6.sin6_len = sizeof(struct sockaddr_in6);
4825 sin6.sin6_addr.s6_addr16[2] = 0xffff;
4826 bcopy(&sin->sin_addr,
4827 &sin6.sin6_addr.s6_addr16[3],
4828 sizeof(sin6.sin6_addr.s6_addr16[3]));
4829 sin6.sin6_port = sin->sin_port;
4830 memcpy(from, (caddr_t)&sin6, sizeof(sin6));
4831 }
4832#endif
4833#if defined(INET6)
4834 {
4835 struct sockaddr_in6 lsa6, *to6;
4836
4837 to6 = (struct sockaddr_in6 *)to;
4838 sctp_recover_scope_mac(to6, (&lsa6));
4839 }
4840#endif
4841 }
--- 632 unchanged lines hidden (view full) ---
5474sctp_m_freem(struct mbuf *mb)
5475{
5476 while (mb != NULL)
5477 mb = sctp_m_free(mb);
5478}
5479
5480#endif
5481
5482int
5483sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id)
5484{
5485 /*
5486 * Given a local address. For all associations that holds the
5487 * address, request a peer-set-primary.
5488 */
5489 struct sctp_ifa *ifa;
5490 struct sctp_laddr *wi;
5491
5492 ifa = sctp_find_ifa_by_addr(sa, vrf_id, 0);
5493 if (ifa == NULL) {
5494 return (EADDRNOTAVAIL);
5495 }
5496 /*
5497 * Now that we have the ifa we must awaken the iterator with this
5498 * message.
5499 */
5500 wi = SCTP_ZONE_GET(sctppcbinfo.ipi_zone_laddr, struct sctp_laddr);
5501 if (wi == NULL) {
5502 return (ENOMEM);
5503 }
5504 /* Now incr the count and int wi structure */
5505 SCTP_INCR_LADDR_COUNT();
5506 bzero(wi, sizeof(*wi));
5507 wi->ifa = ifa;
5508 wi->action = SCTP_SET_PRIM_ADDR;
5509 atomic_add_int(&ifa->refcount, 1);
5510
5511 /* Now add it to the work queue */
5512 SCTP_IPI_ITERATOR_WQ_LOCK();
5513 /*
5514 * Should this really be a tailq? As it is we will process the
5515 * newest first :-0
5516 */
5517 LIST_INSERT_HEAD(&sctppcbinfo.addr_wq, wi, sctp_nxt_addr);
5518 sctp_timer_start(SCTP_TIMER_TYPE_ADDR_WQ,
5519 (struct sctp_inpcb *)NULL,
5520 (struct sctp_tcb *)NULL,
5521 (struct sctp_nets *)NULL);
5522 SCTP_IPI_ITERATOR_WQ_UNLOCK();
5523 return (0);
5524}
5525
5526
5527
5528
5529int
5530sctp_soreceive(so, psa, uio, mp0, controlp, flagsp)
5531 struct socket *so;
5532 struct sockaddr **psa;
5533 struct uio *uio;
5534 struct mbuf **mp0;
5535 struct mbuf **controlp;
5536 int *flagsp;
--- 48 unchanged lines hidden ---